NGINX如何配置允许指定iPhone IP访问WordPress登录页并禁止其他IP
问题背景
运行的LEMP服务器承载WordPress业务状态正常,最初已配置如下规则实现WordPress登录页(www.mysite/wp-login.php)仅允许局域网IP段访问,其余所有IP全部拦截:
server { # 仅允许局域网访问wp-login页面 (www.mysite.com/wp-login.php) location ~ /wp-login.php { allow 192.168.1.0/24; deny all; }
该配置已生效,公网访问wp-login.php全部被拦截,局域网内可正常访问,符合预期。
需求
需要将手机公网IP加入白名单,实现仅允许手机IP和局域网IP访问登录页,其余外网IP仍全部拦截。通过手机访问IP查询平台获取公网IP后,将规则修改为:
server { # 允许局域网和手机访问wp-login页面 (www.mysite.com/wp-login.php) location ~ /wp-login.php { allow 77.232.28.46; # 第三方平台显示的手机IP allow 192.168.1.0/24; deny all; }
问题现象
重载NGINX配置后,手机仍然无法访问wp-login.php页面。
参考配置
nginx.conf完整内容
# Danrancan的LEMP服务器/etc/nginx/nginx.conf文件 # 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; ## # 基础配置 ## 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; # 自定义Nginx日志格式netdata,包含请求时间、上游响应时间,单位为秒,精度毫秒 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配置 ## ssl_session_cache shared:SSL:10m; #SSL会话缓存 ssl_session_timeout 1h; ssl_prefer_server_ciphers on; ## # 日志配置 ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip配置 ## 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; # 额外响应头,用于判断请求是否命中缓存 #add_header Fastcgi-Cache $upstream_cache_status; ## # 虚拟主机配置 ## 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; ## # Nginx抗DDOS加固 ## client_header_timeout 10; # 安全场景建议设置client_body_timeout为10,大文件上传场景可适当调大 client_body_timeout 10; keepalive_timeout 10; send_timeout 10; }
虚拟主机配置完整内容
# Danrancan的虚拟主机配置,路径/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配置(来自Mozilla配置生成器:现代配置) ### # 添加HSTS响应头带always参数,防范MITM攻击 # HSTS(需要ngx_http_headers_module)(63072000秒) add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; ## 添加X-Frame头防范点击劫持 add_header x-frame-options "SAMEORIGIN" always; # 添加内容安全策略头 add_header Content-Security-Policy "frame-ancestors 'self';"; # 添加X-Content-Type-Options头加固MIME类型安全 add_header X-Content-Type-Options nosniff; # 开启X-XSS-Protection头 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=()"; # 签名证书+中级证书路径 ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem; # 管理员维护 ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem; # 管理员维护 # 完美前向保密4096位Diffie-Hellman参数 ssl_dhparam /etc/ssl/private/dhparams4096.pem; # 管理员维护 # 虚拟主机中引入perfect-forward-secrecy.conf,注意:nginx.conf中已全局引入,可注释 #include /etc/nginx/perfect-forward-secrecy.conf; # 管理员维护 # 现代SSL配置,开启OCSP装订 #ssl_protocols TLSv1.3; # 已在nginx.conf中配置,可注释 ssl_prefer_server_ciphers on; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; # 约可存储40000个会话 ssl_session_tickets off; # OCSP装订配置 ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4; # 使用根证书和中级证书验证OCSP响应的信任链 ssl_trusted_certificate /etc/letsencrypt/live/mysite.com/chain.pem; # 管理员维护 server_name mysite.com www.mysite.com; root /var/www/mysite.com; # 错误日志和访问日志 #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; # 已在http块配置,此处无需重复配置 index index.php index.html index.htm; # 仅允许内网IP访问/admin路径 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)(/.+)$; } # 仅允许本地访问wp-login页面 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; } # 静态文件长期缓存 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; } # 隐私加固:拒绝访问隐藏文件 location ~ /\. { deny all; access_log off; log_not_found off; } # 禁止上传目录执行PHP location /wp-content/uploads/ { location ~ \.php$ { deny all; } } # PHP脚本转发到FastCGI服务器 location ~ \.php$ { include snippets/fastcgi-php.conf; # 使用php-fpm(或其他unix套接字): fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.+)$; # 推荐安全配置 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; } }
解决方案
问题原因排查
- IP获取错误:如果站点前置了CDN、反向代理或WAF,NGINX默认获取的
$remote_addr是代理节点IP,不是手机真实公网IP,导致白名单不生效。 - 配置未正确修改:从提供的虚拟主机配置来看,wp-login的location块仍未添加手机IP规则,可能存在修改错配置文件、未做软链接到
sites-enabled目录的问题。 - 手机IP动态变化:运营商公网IP多为动态分配,查询到的IP和实际请求IP可能不一致。
- ModSecurity拦截:配置中开启了ModSecurity WAF,可能是WAF规则拦截了手机请求。
正确配置步骤
- 确认真实请求IP
访问站点access日志/var/log/nginx/mysite.com.access.log,查找手机访问wp-login.php的记录,确认日志第一个字段的IP是否为手机实际出口IP。
如果日志显示IP不是你查询的手机IP,说明存在前置代理,需要在虚拟主机443 server块内添加真实IP获取规则:
# 替换为你的代理/CDN节点IP段 set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; real_ip_recursive on;
- 修改wp-login访问规则
编辑/etc/nginx/sites-available/mysite.com.conf,找到对应location块修改为:
# 允许手机和局域网访问wp-login页面 location ~ /wp-login.php { allow 77.232.28.46; # 替换为日志中查到的手机真实IP 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)(/.+)$; }
- 配置生效
执行nginx -t校验配置语法无错误后,执行systemctl reload nginx重载配置生效。 - 额外排查
如果配置后仍无法访问,可临时关闭ModSecurity测试,将nginx.conf中modsecurity on;修改为modsecurity off;重载后验证,如可访问则调整ModSecurity规则放行手机IP即可。
内容的提问来源于stack exchange,提问作者DanRan
相关产品推荐
相关产品推荐

