• nginx实战-frp+docker+nginx+tomcat内网穿透无法获取客户端真实ip


    部署架构

    浏览器–>frp–>nginx(docker)–>tomcat

    场景描述

    在公网部署了frp服务,在本地内网docker环境下安装好了nginx服务,访问内网中的tomcat,但我查看nginx的日志时,发现记录的ip全是内网docker的ip,没有获取到真实的访问ip。

    172.17.0.1 - - [30/Jun/2022:22:56:45 +0800] "GET /aad7 HTTP/1.1" 400 657 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
    172.17.0.1 - - [30/Jun/2022:23:25:57 +0800] "GET / HTTP/1.1" 200 3956 "-" "Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"
    172.17.0.1 - - [30/Jun/2022:23:26:08 +0800] "PRI * HTTP/2.0" 400 157 "-" "-"
    
    
    • 1
    • 2
    • 3
    • 4

    ifconfig查看本地docker环境的ip,发现nginx获取到的ip全部是docker的gateway的ip

    docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
            inet6 fe80::42:cbff:fe08:3af8  prefixlen 64  scopeid 0x20<link>
            ether 02:42:cb:08:3a:f8  txqueuelen 0  (以太网)
            RX packets 386170  bytes 1055243584 (1.0 GB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 398904  bytes 293451267 (293.4 MB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    原因分析

    查了一下frp文档,文档中简单的说了下,需要在frpc.ini配置文件中 ,需要增加一行 proxy_protocol_version = v2,便可以开启记录真实ip的功能。

    在frpc.ini中修改如下:

    [http_web]
    type = tcp
    local_ip = 127.0.0.1
    local_port = 7443
    remote_port = 7443
    # 目前支持 v1 和 v2 两个版本的 proxy protocol 协议。
    proxy_protocol_version = v2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启frp,结果网站直接打不开了,建立连接失败,总感觉哪里少了些配置,网上翻了一遍,发现在nginx中还需要添加配置。
    nginx是docker跑起来的服务,在listen段添加proxy_protocol,然后配置real_IP_header为 proxy_protocol,具体如下:

    		#listen       443 ssl ;
    		listen       443 ssl http2 proxy_protocol;
    		real_ip_header proxy_protocol;
      		real_ip_recursive on;
      		set_real_ip_from 172.17.0.1;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其中set_real_ip_from的ip为frp客户端的内网IP,我填写的是docker桥接网络的网关地址。
    好了,保存nginx的网站配置文件后,重启Nginx,再查看nginx的日志,就已经可以获取用户的真实IP地址了。
    注意:这样配置之后会导致无法通过

    实战

    frp转发

    http {
    	# 黑名单
    	#include blockips.conf;
        include       mime.types;
        default_type  application/octet-stream;
    	underscores_in_headers on;#表示如果header name中包含下划线,则不忽略
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
    
        gzip  on;
    	#服务器的集群  
    	upstream  www_demo {  #服务器集群名字   
    		# ip_hash; # (通过客户端请求ip进行hash,再通过hash值选择后端server)
    		# hash $request_uri; #(url_hash;通过请求url进行hash,再通过hash值选择后端server)
    		server    192.168.0.55:7228  weight=10;#服务器配置   weight是权重的意思,权重越大,分配的概率越大。  
    		server    127.0.0.1:7228 weight=1;  
    		server    192.168.0.15:7228 backup; # 将该服务器标记为备份服务器,当主服务器不可用时,将用来传递请求
    	} 
    
    	server {
    		#listen       7443 ssl ;
    		listen       7443 ssl http2 proxy_protocol;
    		real_ip_header proxy_protocol;
      		real_ip_recursive on;
      		set_real_ip_from 172.17.0.1;
    		#黑名单
    		include /etc/nginx/conf.d/port_7443.block;
    		#server_name  127.0.0.1;
    		charset utf-8;   #"没错就是这里"
    		max_ranges 1; ## 禁用multipart range分片功能
    	     ssl_certificate       /etc/nginx/ssl/frp.zhuzhu.biz_nginx/frp.zhuzhu.biz.pem;
    		ssl_certificate_key   /etc/nginx/ssl/frp.zhuzhu.biz_nginx/frp.zhuzhu.biz.key;
    
    		ssl_ciphers  HIGH:!aNULL:!MD5;
    		ssl_prefer_server_ciphers  on;
    		
    		# 记录单独日志
    		access_log  logs/7443.access.log;
    
    		# 开始压缩
    		gzip on;
    		gzip_min_length 1k;
    		gzip_comp_level 9;
    		gzip_types text/plain text/s text/javascript application/json application/javascript application/x-javascript application/xml;
    		gzip_vary on;
    		gzip_disable "MSIE [1-6]\.";
    		
    		# 映射一个文件目录
    		location /horizon/{
    			alias   /usr/local/horizon/;
    			sendfile on;
    			autoindex on;  # 开启目录文件列表
    			autoindex_exact_size on;  # 显示出文件的确切大小,单位是bytes
    			autoindex_localtime on;  # 显示的文件时间为文件的服务器时间
    			charset utf-8,gbk;  # 避免中文乱码
    		}
    		
    		# 映射一个html前后单分离目录
    		root /usr/local/nginx/www;
    		
    		location / {
    			index  pc/index.html;
    		}
    		location /static {
    			alias /usr/local/nginx/www/pc/static;
    		}
    		# 映射一个自定义json
    		location /iot/update/check{
    			default_type application/json;
    			return 200 '{"code":0,"data":{"length":101895489,"version":"0.0.6"}}';
    		}
    		
    		
    		location /user {
    			add_header Cache-Control 'no-store';
    			# 设置请求体的最大值,影响上传文件大小
    			client_max_body_size 100m;
    			# 配置客户端ip为真实ip,否则在tomcat获取到的是nginx是ip, $remote_addr获取到上一级代理的IP
             	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_set_header    X-Forwarded-Proto $scheme;
    			#proxy_redirect      default;
    			proxy_redirect off;
    			# 下面两行支持websocket
    			#proxy_http_version 1.1;
    			#proxy_set_header Upgrade $http_upgrade;
    			#proxy_set_header Connection $connection_upgrade;
    			
    			# Nginx与上游服务器尝试建立连接,后端服务器连接的超时时间_发起握⼿等候响应超时时间
    			proxy_connect_timeout      1;
    			# 用于读取上游服务器响应时,最长的读取等待时间,连接成功后_等候后端服务器响应时间_其实已经进如后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
    			proxy_send_timeout         60;
    			# Nginx向上游服务器传输数据时的超时时间
    			proxy_read_timeout         60;
    			proxy_pass http://www_demo;
    		}    
    		   
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110

    多层nginx转发

    # 如果多层nginx转发,则注意如下配置:
    		location ~ ^/(api_v1|share|open_v1|wx|ws|s|p)/.*$ {
    			add_header Access-Control-Allow-Origin *;   #添加跨域访问
    			add_header Access-Control-Allow-Headers X-Requested-With;
    			proxy_pass http://www_sgb_test;
    			proxy_set_header X-Forwarded-Proto $scheme;
    			proxy_set_header Host $host;
    			proxy_set_header Referer $http_referer;
    			#proxy_set_header X-Real-IP $remote_addr;#// 由于clb转发,所以这里不需要再设置
    			proxy_set_header X-Real-Port $remote_port;
    			proxy_set_header X-Real-User $remote_user;
    			#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#// 由于clb转发,所以这里不需要再设置
    			#set_real_ip_from 192.168.0.44;
    			#real_ip_recursive on;
    			#real_ip_header X-Forwarded-For;
    			proxy_http_version 1.1;
    			proxy_set_header Upgrade $http_upgrade;
    			proxy_set_header Connection "upgrade";
    			proxy_connect_timeout   1;
    			proxy_buffering off;
    			chunked_transfer_encoding off;
    			proxy_cache off;
    			proxy_send_timeout      3m;
    			proxy_read_timeout      3m;
    			client_max_body_size    1000m;
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    黑名单

    配置ip清单

    在conf文件夹下面新建blockips.conf
    填入如下内容

    #添加黑名单IP
    deny 42.236.10.0/24;
    # deny 58.59.219.11;
    deny 180.163.220.0/24;
    
    • 1
    • 2
    • 3
    • 4

    说明:

    # 屏蔽单个ip访问
    #deny IP;
    ## 允许单个ip访问
    #allow IP;
    ## 屏蔽所有ip访问
    #deny all;
    ## 允许所有ip访问
    #allow all;
    ##屏蔽整个段即从123.0.0.1到123.255.255.254访问的命令
    #deny 123.0.0.0/8
    ##屏蔽IP段即从123.45.0.1到123.45.255.254访问的命令
    #deny 124.45.0.0/16
    ##屏蔽IP段即从123.45.6.1到123.45.6.254访问的命令
    #deny 123.45.6.0/24
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    开启黑名单

    在http或者server或者具体的location中配置如下即可:

    include blockips.conf;
    
    • 1

    配置参考

    nginx限流和黑名单

    Nginx限流和黑名单配置
    https://www.csdn.net/tags/NtjaEgzsODQ0OTctYmxvZwO0O0OO0O0O.html

    hash_ip

    https://blog.csdn.net/li1325169021/article/details/119429683

    frp转发获取真实ip

    https://www.psay.cn/toss/183.html

  • 相关阅读:
    头歌答案HTML——基础
    基于springboot实现数据可视化
    29.Python面向对象(二)【类:主要讲初始化方法__init__,垃圾回收,继承&多继承,方法重写,super()函数】
    2023第二届中国能源管理&碳中和国际峰会
    mysql中的mvcc机制
    技术干货|昇思MindSpore创新模型EPP-MVSNet-高精高效的三维重建
    手撕红黑树的插入(C++)
    Python程序设计基础2
    Mac/Linux 安装 Go 详解
    【三年面试五年模拟】算法工程师的独孤九剑秘籍(第七式)
  • 原文地址:https://blog.csdn.net/Blueeyedboy521/article/details/125552721