糖醋鱼的小破站

🐟生成长记

什么都明白的人 最温柔也最冷漠
你一定要记得 别让一直温柔待你的人寒了心
我是一个不会哭的孩子,所以一直没有糖吃。
  menu
116 文章
7 评论
10486 浏览
1 当前访客
ღゝ◡╹)ノ❤️

2019-07-27-nginx+wordpress-docker镜像获取真实IP

2019-07-27-nginx+wordpress-docker镜像获取真实IP

因为想偷懒以及维护的方面、所以就将我的博客 docker 化了、采用了 nginx 在前、apache 在后的架构。在完成了构建以及启动之后、我发现 WP 统计 这个插件获取不到真实的用户IP、导致访问的IP全是 docker 容器的IP。让人好生郁闷。

获取真实IP的方法

nginx 获取真实IP的方法

因为我是使用 nginx 将用户的请求反向代理回送至后端的 wordpress 镜像的,所以最先是拿它下手的,话不多说放配置文件。

## 主配置文件
user  root root;
worker_processes 4;
error_log  /www/wwwlogs/nginx_error.log  error;
pid        /var/run/nginx.pid;
worker_rlimit_nofile 51200;

events
{
    use epoll;
    worker_connections 51200;
    multi_accept on;
}

http
    {
	server_tokens off;

        include       mime.types;
	#include luawaf.conf;

	include proxy.conf;

    default_type  application/octet-stream;

    server_names_hash_bucket_size 512;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 1000m;

    sendfile   on;
    tcp_nopush on;

    keepalive_timeout 600;

    tcp_nodelay on;

    fastcgi_connect_timeout 600;
    fastcgi_send_timeout 600;
    fastcgi_read_timeout 600;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;

    gzip off;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 2;
    gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
    gzip_vary on;
    gzip_proxied   expired no-cache no-store private auth;
    gzip_disable   "MSIE [1-6]\.";

    limit_conn_zone $binary_remote_addr zone=perip:10m;
	limit_conn_zone $server_name zone=perserver:10m;

	# set user real ip to remote addr
	# set_real_ip_from   192.168.0.0/16;
	set_real_ip_from   172.20.0.0/16;
	real_ip_header     X-Forwarded-For;
	real_ip_recursive on;        
	
	#log_format combined_realip;
	
	log_format  compression '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log on;
	access_log /www/wwwlogs/nginx_access.log compression;

	include /etc/nginx/conf.d/*.conf;
}

nginx 虚拟主机配置文件

server
{
    listen 80;
    listen 443 ssl http2;
    server_name expoli.tech;
    
    #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
    #error_page 404/404.html;
    #HTTP_TO_HTTPS_START
    # if ($server_port !~ 443){
    #     rewrite ^(/.*)$ https://$host$1 permanent;
    # }

    #HTTP_TO_HTTPS_END
    ssl_certificate         /var/www/ssl/www.expoli.tech_nginx/www.expoli.tech.pem;
    ssl_certificate_key     /var/www/ssl/www.expoli.tech_nginx/www.expoli.tech.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    error_page 497  https://$host$request_uri;

    #SSL-END

    location / {
        # 保证获取到真实IP
        proxy_set_header X-Real-IP $remote_addr;
        # 真实端口号
        proxy_set_header X-Real-Port $remote_port;
        # X-Forwarded-For 是一个 HTTP 扩展头部。
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # 在多级代理的情况下,记录每次代理之前的客户端真实ip 
        proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr;
        # 获取到真实协议
        proxy_set_header X-Forwarded-Proto $scheme;
        # 真实主机名
        proxy_set_header Host $host;
        # 设置变量
        proxy_set_header X-NginX-Proxy true;

        proxy_pass http://tcy_wp_web:80;
        proxy_redirect default;

        # Socket.IO Support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    
    access_log on;
    access_log  /www/wwwlogs/expoli.tech.log compression;
    error_log  /www/wwwlogs/expoli.tech.error.log;
}

测试

经过测试发现、wordpress 还是无法正常获取到真实IP。按道理来说、已经配置成功了。不知道细心的你发现没有那就是、wordpress 镜像默认是使用 apache 做 web 服务器 的所以现在的情况是、与后端之间存在了两层代理,即 一级代理 nginx;二级代理 apache、之所以后端获取不到是因为还未在 apache 上进行相关配置、将真实IP传递到 REMOTE_ADDR 变量中(wordpress 统计插件默认取REMOTE_ADDR变量的值。

  • 测试结果:
```json
Array
(
    [HTTP_X_REAL_IP] => 202.***.***.***     // nginx 配置已经生效
    [HTTP_X_REAL_PORT] => 10469
    [HTTP_X_FORWARDED_PROTO] => http        // nginx 配置已经生效
    [HTTP_HOST] => expoli.tech              // nginx 配置已经生效
    [HTTP_X_NGINX_PROXY] => true            // nginx 配置已经生效
    [HTTP_CONNECTION] => upgrade            // nginx 配置已经生效
    [HTTP_PRAGMA] => no-cache
    [HTTP_CACHE_CONTROL] => no-cache
    [HTTP_UPGRADE_INSECURE_REQUESTS] => 1
    [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
    [HTTP_DNT] => 1
    ...
    [SERVER_SOFTWARE] => Apache/2.4.25 (Debian)
    [SERVER_NAME] => expoli.tech
    [SERVER_ADDR] => 172.20.0.3
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 172.20.0.4     // 依旧是 docker 容器Ip
    [DOCUMENT_ROOT] => /var/www/html
    [REQUEST_SCHEME] => http
    [CONTEXT_PREFIX] => 
    [CONTEXT_DOCUMENT_ROOT] => /var/www/html
    [SERVER_ADMIN] => webmaster@localhost
    [SCRIPT_FILENAME] => /var/www/html/info.php
    [REMOTE_PORT] => 40286
 

配置 apache 以获取用户真实IP

经过多方搜集尝试,了解到 apache2.4提供了自带的remoteip模块可以实现获取真实ip。

/etc/apache2/mods-available 文件夹内的 remoteip.load 复制到 /etc/apache2/mods-enabled/ 文件目录下,并新建配置文件 remoteip.conf

注意:因为考虑到容器大小、所以镜像内并没有集成编辑器、需要临时安装、而且容器一旦删除、已经安装的软件也会没有、不过咱们现在只是做个测试、可以直接安装进行更改测试。

apt-get update
apt-get install nano -y
  • remoteip.load
# cat remoteip.load 
LoadModule remoteip_module /usr/lib/apache2/modules/mod_remoteip.so
  • remoteip.conf
# remoteip.conf
RemoteIPHeader X-Forwarded-For
RemoteIPProxiesHeader X-Forwarded-By
  • 测试结果
Array
(
    [HTTP_X_REAL_IP] => 202.***.***.***
    [HTTP_X_REAL_PORT] => 10469
    [HTTP_X_FORWARDED_PROTO] => http
    [HTTP_HOST] => expoli.tech
    [HTTP_X_NGINX_PROXY] => true
    [HTTP_CONNECTION] => upgrade
    [HTTP_PRAGMA] => no-cache
    [HTTP_CACHE_CONTROL] => no-cache
    [HTTP_UPGRADE_INSECURE_REQUESTS] => 1
    [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
    [HTTP_DNT] => 1
    ...
    [SERVER_SOFTWARE] => Apache/2.4.25 (Debian)
    [SERVER_NAME] => expoli.tech
    [SERVER_ADDR] => 172.20.0.3
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 202.***.***.***        // 成功获取到真实IP
    [DOCUMENT_ROOT] => /var/www/html
    [REQUEST_SCHEME] => http
    [CONTEXT_PREFIX] => 
    [CONTEXT_DOCUMENT_ROOT] => /var/www/html
    [SERVER_ADMIN] => webmaster@localhost
    [SCRIPT_FILENAME] => /var/www/html/info.php
    [REMOTE_PORT] => 40286
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    ...
}

修改 docker-compose.yaml 配置文件

1. 查看相关配置文件的路径

docker exec -it $your_container_name /etc/apache2/
total 88
drwxr-xr-x 1 root root  4096 Jun 27 23:44 .
drwxr-xr-x 1 root root  4096 Jul 27 11:24 ..
-rw-r--r-- 1 root root  7224 Apr  2 19:05 apache2.conf
drwxr-xr-x 1 root root  4096 Jun 27 23:44 conf-available
drwxr-xr-x 1 root root  4096 Jun 27 23:44 conf-enabled
-rw-r--r-- 1 root root  1924 Jun 27 23:44 envvars
-rw-r--r-- 1 root root 31063 Nov  3  2018 magic
drwxr-xr-x 1 root root  4096 Jul  3 20:52 mods-available    # 可用模块目录
drwxr-xr-x 1 root root  4096 Jul 27 11:24 mods-enabled      # 已启用模块目录
-rw-r--r-- 1 root root   320 Nov  3  2018 ports.conf
drwxr-xr-x 2 root root  4096 Jun 27 23:44 sites-available
drwxr-xr-x 2 root root  4096 Jun 27 23:44 sites-enabled

2. 查看已启用模块配置文件夹

从下面可以看出启用模块的方式就是创建一个链接、将 mods-available 内的文件链接至 mods-enabled 文件夹、所以我们若想启用 remoteip 模块、只需将 remoteip.conf remoteip.load 文件放入即可。

docker exec -it $your_container_name /bin/bash
cd /etc/apache2/mods-enabled
ls -al
total 20
drwxr-xr-x 1 root root 4096 Jul 27 11:24 .
drwxr-xr-x 1 root root 4096 Jun 27 23:44 ..
lrwxrwxrwx 1 root root   36 Jun 27 23:44 access_compat.load -> ../mods-available/access_compat.load
lrwxrwxrwx 1 root root   28 Jun 27 23:44 alias.conf -> ../mods-available/alias.conf
lrwxrwxrwx 1 root root   28 Jun 27 23:44 alias.load -> ../mods-available/alias.load
...
lrwxrwxrwx 1 root root   32 Jun 27 23:44 autoindex.conf -> ../mods-available/autoindex.conf
lrwxrwxrwx 1 root root   32 Jun 27 23:44 autoindex.load -> ../mods-available/autoindex.load
lrwxrwxrwx 1 root root   30 Jun 27 23:44 deflate.conf -> ../mods-available/deflate.conf
lrwxrwxrwx 1 root root   30 Jun 27 23:44 deflate.load -> ../mods-available/deflate.load
...
lrwxrwxrwx 1 root root   34 Jun 27 23:44 mpm_prefork.conf -> ../mods-available/mpm_prefork.conf
lrwxrwxrwx 1 root root   34 Jun 27 23:44 mpm_prefork.load -> ../mods-available/mpm_prefork.load
lrwxrwxrwx 1 root root   34 Jun 27 23:44 negotiation.conf -> ../mods-available/negotiation.conf
lrwxrwxrwx 1 root root   34 Jun 27 23:44 negotiation.load -> ../mods-available/negotiation.load
lrwxrwxrwx 1 root root   27 Jul  3 20:52 php7.load -> ../mods-available/php7.load
...
lrwxrwxrwx 1 root root   29 Jun 27 23:44 status.load -> ../mods-available/status.load

3. 修改 docker-compose.yaml 文件、挂载相应文件

  1. 在宿主机上创建相应文件
  • remoteip.load
# cat remoteip.load 
LoadModule remoteip_module /usr/lib/apache2/modules/mod_remoteip.so
  • remoteip.conf
# remoteip.conf
RemoteIPHeader X-Forwarded-For
RemoteIPProxiesHeader X-Forwarded-By
  1. 修改 wordpress 服务的相关配置项
version: '3'
services:
    wordpress:
        image: wordpress
        restart: always
        # ports:
        #     - 8090:80
        volumes:
            - ${PWD}/web:/var/www/html:rw
            # remoteip.load
            - ./apache/remoteip.load:/etc/apache2/mods-enabled/remoteip.load:ro
            # remoteip.conf
            - ./apache/remoteip.conf:/etc/apache2/mods-enabled/remoteip.conf:ro
  1. 重建容器
docker-compose stop
docker-compose rm
docker-compose up -d
  1. 测试

可以看出文件已经挂载成功

docker exec -it $your_container_name /bin/bash
cd /etc/apache2/mods-enabled
ls -al
total 20
drwxr-xr-x 1 root root 4096 Jul 27 11:24 .
drwxr-xr-x 1 root root 4096 Jun 27 23:44 ..
lrwxrwxrwx 1 root root   36 Jun 27 23:44 access_compat.load -> ../mods-available/access_compat.load
...
lrwxrwxrwx 1 root root   32 Jun 27 23:44 autoindex.conf -> ../mods-available/autoindex.conf
lrwxrwxrwx 1 root root   32 Jun 27 23:44 autoindex.load -> ../mods-available/autoindex.load
lrwxrwxrwx 1 root root   30 Jun 27 23:44 deflate.conf -> ../mods-available/deflate.conf
...
-rwxrwxrwx 1 root root   69 Jul 27 11:16 remoteip.conf  # 这里
-rwxrwxrwx 1 root root   68 Jul 27 11:14 remoteip.load  # 这里
lrwxrwxrwx 1 root root   33 Jun 27 23:44 reqtimeout.conf -> ../mods-available/reqtimeout.conf
...
  • 测试正常、收工!
Array
(
    [HTTP_X_REAL_IP] => 202.***.***.***
    [HTTP_X_REAL_PORT] => 10469
    [HTTP_X_FORWARDED_PROTO] => http
    [HTTP_HOST] => expoli.tech
    [HTTP_X_NGINX_PROXY] => true
    [HTTP_CONNECTION] => upgrade
    [HTTP_PRAGMA] => no-cache
    [HTTP_CACHE_CONTROL] => no-cache
    [HTTP_UPGRADE_INSECURE_REQUESTS] => 1
    [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
    [HTTP_DNT] => 1
    ...
    [SERVER_SOFTWARE] => Apache/2.4.25 (Debian)
    [SERVER_NAME] => expoli.tech
    [SERVER_ADDR] => 172.20.0.3
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 202.***.***.***        // 成功获取到真实IP
    [DOCUMENT_ROOT] => /var/www/html
    [REQUEST_SCHEME] => http
    [CONTEXT_PREFIX] => 
    [CONTEXT_DOCUMENT_ROOT] => /var/www/html
    [SERVER_ADMIN] => webmaster@localhost
    [SCRIPT_FILENAME] => /var/www/html/info.php
    [REMOTE_PORT] => 40286
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    ...
}


标题:2019-07-27-nginx+wordpress-docker镜像获取真实IP
作者:expoli
地址:https://expoli.tech/articles/2019/07/27/1564656217457.html

评论