NGINX - Directive to Allow iPhone's IP address for accessing wordpress login page (mysite.com/wp-login.php), and Deny all other IP addresses

Viewed 148

MY ENVIRONMENT:

I am running a LEMP server which is working and running wordpress quite properly. As of now, I have my wordpress web login (www.mysite/wp-login.php) blacklisted by all IP addresses EXCEPT any IP on my LAN with the following directive:

server {
    # Allow LAN only on wp-login page (www.mysite.com/wp-login.php)
    location ~ /wp-login.php {
        allow 192.168.1.0/24;
        deny all;
    }

This directive sucessfully blocks all internet traffic to "mywebsite.com/wp-login.php", which is the wordpress admin login page. In other words, with this directive set, I can access the wordpress login page anywhere on my internal LAN, but the directive denys any outside internet traffic from seeing the "mywebsite.com/wp-login.php" page. GREAT!

WHAT I WANT TO DO,

is to whitelist the IP address of my phone, so that I can access the wordpress login page from my phone's IP address, while still blocking any other outside internet traffic. To do so, I go to www.whatsmyip.org on my phone, copy the ip address that it gives me, then modify the previous directive to look like the following:

server {
    # Allow LAN and CellPhone access to to wp-login page (www.mysite.com/wp-login.php)
    location ~ /wp-login.php {
        allow 77.232.28.46; # my phones ip address as shown on whatsmyip.org
        allow 192.168.1.0/24;
        deny all;
    }

HOWEVER,

after reloading nginx, I still cannot access the wp-login (wordpress login) page from my phone.

MY QUESTION IS:

Using NGINX, How can I properly whitelist my phones IP address, while blacklisting everything else access to the wordpress login page locate at www.mysite.com/wp-login.php ?

FOR REFERENCE:

Below is my NGINX.CONF file:

# This is the /etc/nginx/nginx.conf file for Danrancan's LEMP server
#
user www-data;
worker_processes 4;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
load_module /usr/share/nginx/modules/ngx_http_modsecurity_module.so;
 
events {
    worker_connections 1024;
    # multi_accept on;
}
 
http {
    ##
    # Mod Security
    ##
    modsecurity on;
    #modsecurity off;
    modsecurity_rules_file /etc/nginx/modsec/main.conf;
 
    ##
    # Basic Settings
    ##
    client_max_body_size 512M;
    fastcgi_read_timeout 300;
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    types_hash_max_size 4096;
    server_tokens off;
 
    server_names_hash_bucket_size 64;
    # server_name_in_redirect off;
 
# Create a custom Nginx log format called netdata that includes information about request_time, and upstream_response_time, measured in seconds with millisecond resolution.
log_format netdata '$remote_addr - $remote_user [$time_local] '
              '"$request" $status $body_bytes_sent '
              '$request_length $request_time $upstream_response_time '
              '"$http_referer" "$http_user_agent"';
 
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
 
    ##
    # SSL Settings
    ##
 
    ssl_session_cache shared:SSL:10m;   #SSL session cache
    ssl_session_timeout 1h;
    ssl_prefer_server_ciphers on;
 
    ##
    # Logging Settings
    ##
 
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
 
    ##
    # Gzip Settings
    ##
 
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
        application/atom+xml
        application/javascript
        application/json
        application/rss+xml
        application/vnd.ms-fontobject
        application/x-font-ttf
        application/x-web-app-manifest+json
        application/xhtml+xml
        application/xml
        font/opentype
        image/svg+xml
        image/x-icon
        text/css
        text/plain
        text/x-component
        text/javascript
        text/xml;
 
    # Extra Http Header response to determine whether a request is being served from the cache
    #add_header Fastcgi-Cache $upstream_cache_status;
 
    ##
    # Virtual Host Configs
    ##
 
    upstream local_php {
        server unix:/run/php/php7.4-fpm.sock;
    }
 
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
    include /etc/nginx/perfect-forward-secrecy.conf;
 
    ##
    # Harden nginx against DDOS. #noted from www.pestmeester.nl
    ##
 
    client_header_timeout 10;
    # For good security, set client_body_timeout to 10. For uploading large files, set to higher.
    client_body_timeout   10;
    keepalive_timeout     10;
    send_timeout          10;
}

and my VIRTUAL HOST CONFIG:

# Danrancan's Virtual host config for /etc/nginx/sites-available/mysite.com.conf
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name mysite.com www.mysite.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;

    ###
    # SSL (From Mozilla Config Generator: Modern Configuration)
    ###

    # Add Strict Transport Security Response Header with "always Paramater", to help prevent MITM attacks.
    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;

    ## Prevent click jacking by adding an X-Frame header

    # Add X-Frame-Options header to nginx with the following line:
    add_header x-frame-options "SAMEORIGIN" always;

    # Add a content security policy header
    add_header Content-Security-Policy "frame-ancestors 'self';";

    # Secure MIME Types with X-Content-Type-Options. Below line adds the X-Fram-Options header in Nginx.
    add_header X-Content-Type-Options nosniff;

    # Enable X-XSS-Protection header in Nginx
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy "strict-origin";
    add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";

    # Path to signerd certificate + Intermediate certificates
    ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # Managed by admin
    ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # Managed by admin

    # Perfect Forward Secrecy Diffie-Hellman 4096 parameters
    ssl_dhparam /etc/ssl/private/dhparams4096.pem; # Managed by admin

    # Include "perfect-forward-secrecy.conf" file in this virtual host. NOTE: No need to do this, as its already included in the nginx.conf file, so you should comment this out.
    #include /etc/nginx/perfect-forward-secrecy.conf; # Managed by admin

    # Modern SSL configuration with OCSP stapling turned on
    #ssl_protocols TLSv1.3; # commented out because its already in the nginx.conf file
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4;
    # Verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /etc/letsencrypt/live/mysite.com/chain.pem; # Managed by admin

    server_name mysite.com  www.mysite.com;
    root /var/www/mysite.com;

    # Error & Access Logs
    #error_log /var/www/mysite.com.logs/error.log error;
    #access_log /var/www/mysite.com.logs/access.log;
    access_log /var/log/nginx/mysite.com.access.log netdata;
    error_log /var/log/nginx/mysite.com.error.log warn;

    # This should be in your http block and if it is, it's not needed here.
    index index.php index.html index.htm;

    # Only allow access of /admin via internal IP
    location ^~ /admin {
        allow 192.168.1.0/24;
        deny all;
        error_page 403 =444;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
    }

    # Allow local only to wp-login page
    location ~ /wp-login.php {
        allow 192.168.1.0/24;
        deny all;
        error_page 403 =444;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
    }

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ /.well-known {
        allow all;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # Cache Static Files For As Long As Possible
    location ~*\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log off;
        log_not_found off;
        expires max;
    }

    # Security Settings For Better Privacy Deny Hidden Files
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }

    # Disallow PHP In Upload Folder
    location /wp-content/uploads/ {
        location ~ \.php$ {
        deny all;
        }
    }

    # Pass PHP scripts to FastCGI server
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        # With php-fpm (or other unix sockets):
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # Below was Added from recommended by pestmeester.nl
        fastcgi_intercept_errors on;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
    }
}
1 Answers

What you are doing should work.
Since it is not, it seems that for some reason nginx doesn't see your phone IP as a match to what you have configured.

It sounds like your WP box is running on a private network (because of the 192.168.1.0/ IP addresses you mentioned).

When you connect to the WP box from the internet, is it going through a router with port forwarding/NAT?

First thing I would do is just tail your nginx access log (access_log /var/log/nginx/access.log;) when trying to access with your iphone and see what is reported.

If the request is coming through a proxy/reverse-proxy you may need to make sure the proxy is adding X-Forwarded-For to pass along the remote (iphone) ip address. The request to nginx/wp would be coming from the proxy IP and there would be a header X-Forwarded-For added to the request containing the original remote address.

When nginx is used this way you need to use nginx's realip module...something like:

real_ip_header X-Forwarded-For;
set_real_ip_from 192.168.1.1;  # proxy ip

http://nginx.org/en/docs/http/ngx_http_realip_module.html

Related