ML
    • Recent
    • Categories
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    How To Allow Site Access In Nginx By DDNS Instead Of By IP

    IT Discussion
    how to nginx dynamicdns
    3
    8
    9.1k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • NashBrydgesN
      NashBrydges
      last edited by NashBrydges

      In a previous post, I was looking for a way to allow access to a website behind a Nginx proxy based on a dynamic DNS domain. I had already set the allow/deny statements in the config file for the IP ranges assigned to the company, now I just needed a way to also allow access for the CEO from home when he has a dynamic IP.

      The beauty of this, for this setup, is that I can allow access from within the config file "location" and this could be different for each of the domains configured on this Nginx instance.

      Btw, credit where credit is due.
      https://blog.zencoffee.org/2013/12/dynamic-dns-filtering-nginx/

      First, here is the config file before with the allow/deny rules for the IP ranges. This company has 2 sets of assigned IP ranges.

      server {
         listen 80;
         server_name domain.ca;
         return 301 https://$server_name$request_uri;
      }
      
      server {
        listen 443 ssl http2;
        server_name domain.ca;
        
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Content-Type-Options nosniff;
        add_header Referrer-Policy strict-origin;
        add_header Content-Security-Policy "default-src" always;
        add_header X-Frame-Options SAMEORIGIN;
        ssl_stapling on;
        ssl_stapling_verify on;
        server_tokens off;
      
        ssl on;
        ssl_certificate /etc/letsencrypt/live/domain.ca/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/domain.ca/privkey.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        proxy_cookie_path / "/; secure; HttpOnly";
      
      
          location / {
          	allow 192.168.1.0/24; #obviously not the real IP range but represents IP range 1
              allow 192.168.2.0/24; #obviously not the real IP range but represents IP range 2
              deny all; #deny all other IPs
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header Host $http_host;
              proxy_set_header X-NginX-Proxy true;
              proxy_pass http://192.168.100.61;
              proxy_redirect off;
      
              # Socket.IO Support
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
         }
      }
      

      Step 1:
      I created a new file at /etc/cron.daily/ and named it getddns

      Step 2
      Added this code to the new file

      #!/bin/bash
      host mydynamicdomain.ddns.net | grep "has address" | sed 's/.*has address //' | awk '{print "allow\t\t" $1 ";\t\t# DDNS IP" }' > /etc/nginx/conf.d/homeip.inc
      service nginx reload > /dev/null 2>&1
      

      This will get the IP address for the DDNS domain and inserts it into a file named "/etc/nginx/conf.d/homeip.inc", then reloads Nginx.

      Step 3
      Make the new file executable

      sudo chmod +x /etc/cron.daily/getddns
      

      Step 4*
      Change the config file to include the new homeip.inc file which contains the allow statement for the DDNS domain. You can see the new line in the "location".

      server {
         listen 80;
         server_name domain.ca;
         return 301 https://$server_name$request_uri;
      }
      
      server {
        listen 443 ssl http2;
        server_name domain.ca;
        
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Content-Type-Options nosniff;
        add_header Referrer-Policy strict-origin;
        add_header Content-Security-Policy "default-src" always;
        add_header X-Frame-Options SAMEORIGIN;
        ssl_stapling on;
        ssl_stapling_verify on;
        server_tokens off;
      
        ssl on;
        ssl_certificate /etc/letsencrypt/live/domain.ca/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/domain.ca/privkey.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        proxy_cookie_path / "/; secure; HttpOnly";
      
      
          location / {
              include /etc/nginx/conf.d/homeip.inc; #THIS IS THE NEW LINE
          	allow 192.168.1.0/24; #obviously not the real IP range but represents IP range 1
              allow 192.168.2.0/24; #obviously not the real IP range but represents IP range 2
              deny all; #deny all other IPs
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header Host $http_host;
              proxy_set_header X-NginX-Proxy true;
              proxy_pass http://192.168.100.61;
              proxy_redirect off;
      
              # Socket.IO Support
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection "upgrade";
         }
      }
      

      That's it. Now the allow/deny rules will be updated once an hour with any changes to the dynamic IP address.

      This is scheduled to run every hour but could be run every day instead if that's too frequent.

      The nice thing about this option rather than using the firewall script from @Romo here is that, users can be presented with an appropriate Access Denied 403 page rather than being blocked at the firewall. For a service like the PiHole, @Romo's script makes more sense but for a website, I like the ability to present the access denied page.

      Edit: Updated for spelling in title

      JaredBuschJ 1 Reply Last reply Reply Quote 1
      • JaredBuschJ
        JaredBusch
        last edited by

        Retitle the topic appropriately.

        NashBrydgesN 1 Reply Last reply Reply Quote 0
        • JaredBuschJ
          JaredBusch
          last edited by

          This is what I meant when I said look at the other post to get the IP from DynDNS. I did not mean to use the other script. It is a different scenario.

          1 Reply Last reply Reply Quote 0
          • NashBrydgesN
            NashBrydges @JaredBusch
            last edited by

            @jaredbusch said in Hot To Allow Site Access In Nginx By DDNS Instead Of By IP:

            Retitle the topic appropriately.

            If I thought the topic title wasn't appropriate, I would have titled it differently. I'm not married to the title so if you feel another title would better describe what's here, feel free to make a suggestion.

            JaredBuschJ 1 Reply Last reply Reply Quote 0
            • JaredBuschJ
              JaredBusch @NashBrydges
              last edited by

              @nashbrydges said in Hot To Allow Site Access In Nginx By DDNS Instead Of By IP:

              #!/bin/bash
              host mydynamicdomain.ddns.net | grep "has address" | sed 's/.*has address //' | awk '{print "allow\t\t" $1 ";\t\t# DDNS IP" }' > /etc/nginx/conf.d/homeip.inc
              service nginx reload > /dev/null 2>&1
              

              This will get the IP address for the DDNS domain and inserts it into a file named "/etc/nginx/conf.d/homeip.inc", then reloads Nginx.

              This will only work for a single dyndns domain. You will have to duplicate this for each user. You have said this was for more than one user.

              It would be better to make the script a bit smarter.

              Have it read the dyndns names from an input file andhave it populate all of them into a single include file.

              1. This means you do not have to edit the crontab to make changes.
              2. This mean you do not have to have multiple includes and multiple crons.
              NashBrydgesN 1 Reply Last reply Reply Quote 0
              • JaredBuschJ
                JaredBusch @NashBrydges
                last edited by

                @nashbrydges said in Hot To Allow Site Access In Nginx By DDNS Instead Of By IP:

                @jaredbusch said in Hot To Allow Site Access In Nginx By DDNS Instead Of By IP:

                Retitle the topic appropriately.

                If I thought the topic title wasn't appropriate, I would have titled it differently. I'm not married to the title so if you feel another title would better describe what's here, feel free to make a suggestion.

                0_1507225889817_309cbcfc-2fed-46e6-bc1c-b2abc864ea99-image.png

                1 Reply Last reply Reply Quote 0
                • NashBrydgesN
                  NashBrydges @JaredBusch
                  last edited by

                  @jaredbusch said in Hot To Allow Site Access In Nginx By DDNS Instead Of By IP:

                  @nashbrydges said in Hot To Allow Site Access In Nginx By DDNS Instead Of By IP:

                  #!/bin/bash
                  host mydynamicdomain.ddns.net | grep "has address" | sed 's/.*has address //' | awk '{print "allow\t\t" $1 ";\t\t# DDNS IP" }' > /etc/nginx/conf.d/homeip.inc
                  service nginx reload > /dev/null 2>&1
                  

                  This will get the IP address for the DDNS domain and inserts it into a file named "/etc/nginx/conf.d/homeip.inc", then reloads Nginx.

                  This will only work for a single dyndns domain. You will have to duplicate this for each user. You have said this was for more than one user.

                  It would be better to make the script a bit smarter.

                  Have it read the dyndns names from an input file andhave it populate all of them into a single include file.

                  1. This means you do not have to edit the crontab to make changes.
                  2. This mean you do not have to have multiple includes and multiple crons.

                  That's correct, Nowhere in this thread does it say it works for more than a single user. This however is very useful for me in cases where it will be used for a single user. And this is also a good place for me to start to see if I can adapt it or modify it for more than 1 user. A great learning opportunity for me and others who are still relatively new to using Nginx or Linux.

                  1 Reply Last reply Reply Quote 0
                  • stacksofplatesS
                    stacksofplates
                    last edited by stacksofplates

                    I haven’t tried it but process substitution may work if you enable envsubst.

                    So rather than an include you might just be able to do:

                    $( nslookup domain.com | yada yada)
                    

                    Driving so don’t feel like typing out anything.

                    1 Reply Last reply Reply Quote 0
                    • 1 / 1
                    • First post
                      Last post