Nginx 擔任 Web Proxy 傳遞真實 IP 的設定方式

困擾很久經過 Nginx 擔任的 Proxy 無法傳遞 Real IP 到 Web Server 的問題終於找到解法.

  • 首先要確認 Nginx 編譯時是否有 –with-http_realip_module 確認方式如下
    nginx -V
    [root@ct-wiki ~]# nginx -V
    nginx version: nginx/1.14.2
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
    built with OpenSSL 1.0.2k-fips  26 Jan 2017
    TLS SNI support enabled
    configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

    如果 configure arguments: 後面有出現 –with-http_realip_module 就表示目前執行的 nginx 編譯時有納入該模組

  • 官網提供給 CentOS 7 的版本預設就有納入 –with-http_realip_module
  • 實際設定驗證環境:
    • CloudFlare CDN → Nginx Proxy (192.168.11.234) → Nginx Web Server(192.168.11.233)
  • 編輯 Proxy 內轉給 www.ichiayi.com 的設定檔 www_ichiayi.conf
    vi /etc/nginx/conf.d/www_ichiayi.conf
    server {
            server_name     www.ichiayi.com;
    
            access_log /var/log/nginx/www.ichiayi.com.access.log main;
            error_log /var/log/nginx/www.ichiayi.com.error.log;
    
    # Cloudflare IP List
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 131.0.72.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 2400:cb00::/32;
    set_real_ip_from 2606:4700::/32;
    set_real_ip_from 2803:f800::/32;
    set_real_ip_from 2405:b500::/32;
    set_real_ip_from 2405:8100::/32;
    set_real_ip_from 2c0f:f248::/32;
    set_real_ip_from 2a06:98c0::/29;
    
    # use any of the following two
    #real_ip_header CF-Connecting-IP;
    real_ip_header X-Forwarded-For;
    
            location / {
                    set_real_ip_from  192.168.11.0/24;
                    real_ip_header    X-Forwarded-For;
                    real_ip_recursive on;
    
                    proxy_pass       http://192.168.11.233:80;
                    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
                    proxy_redirect off;
                    proxy_buffering off;
                    proxy_set_header Host      $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    :
    :
  • 設定完成後看到的 log 檔就可看到來源實際 IP, 不會是 CloudFlare 的 Proxy IP
    :
    46.229.168.142 - - [11/Feb/2019:18:46:51 +0800] "GET /wiki/bicycle/20100422?do=media&image=tech%3Aditaa_concept_e2c8f1a6d825fe2154e6ca46354651b5.png&ns=tech&tab_details=view&tab_files=files HTTP/1.1" 200 18868 "-" "Mozilla/5.0 (compatible; SemrushBot/3~bl; +http://www.semrush.com/bot.html)" "46.229.168.142"
    46.229.168.129 - - [11/Feb/2019:18:46:59 +0800] "GET /wiki/tech/kvm?do=media&image=tech%3Aclientca%3Acca_07.png&ns=tech%3Aclientca&tab_details=view&tab_files=upload HTTP/1.1" 200 5487 "-" "Mozilla/5.0 (compatible; SemrushBot/3~bl; +http://www.semrush.com/bot.html)" "46.229.168.129"
    :
  • CloudFlare 傳遞過來出現的 log 最後面本來也會出現實際來源 IP Exp. “46.229.168.129”
  • 編輯 Web Server 內 www.ichiayi.com 的設定檔 default.conf
    vi /etc/nginx/conf.d/default.conf 
    server {
      listen 80;
      server_name www.ichiayi.com;
      autoindex off;
      client_max_body_size 15M;
      client_body_buffer_size 128k;
      index index.html index.htm index.php doku.php;
      access_log  /var/log/nginx/wiki.ichiayi.com/access.log;
      error_log  /var/log/nginx/wiki.ichiayi.com/error.log;
      root /var/www/html;
    
    set_real_ip_from 192.168.11.234/32;
    # use any of the following two
    #real_ip_header CF-Connecting-IP;
    real_ip_header X-Forwarded-For;
    
      location / {
        try_files $uri $uri/ @wiki;
      }
    
      location ~ ^/wiki/lib.*\.(gif|png|ico|jpg)$ {
        expires 30d;
      }
    :
    :
  • 設定完成後看到的 log 檔就可看到來源實際 IP, 不會是 Proxy IP 192.168.11.234
    :
    46.229.168.142 - - [11/Feb/2019:18:46:51 +0800] "GET /wiki/bicycle/20100422?do=media&image=tech%3Aditaa_concept_e2c8f1a6d825fe2154e6ca46354651b5.png&ns=tech&tab_details=view&tab_files=files HTTP/1.0" 200 18825 "-" "Mozilla/5.0 (compatible; SemrushBot/3~bl; +http://www.semrush.com/bot.html)"
    46.229.168.129 - - [11/Feb/2019:18:46:59 +0800] "GET /wiki/tech/kvm?do=media&image=tech%3Aclientca%3Acca_07.png&ns=tech%3Aclientca&tab_details=view&tab_files=upload HTTP/1.0" 200 5468 "-" "Mozilla/5.0 (compatible; SemrushBot/3~bl; +http://www.semrush.com/bot.html)"
    :
  • 和 Proxy 內的 Log 相同, 只是少了 CloudFlare 提供最後的 IP 欄位
  • 一開始設定是使用 CF-Connecting-IP 但發現透過 vpn 內部連線無法轉回 vpn IP 而是 Proxy IP, 所以改成 X-Forwarded-For 就可以看到來自 vpn 的 IP.
  • tech/nginx_proxy_real_ip.txt
  • 上一次變更: 2021/04/09 10:29
  • jonathan