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

目录

  • 部署架构
  • 场景描述
  • 原因分析
  • 实战
    • frp转发
    • 多层nginx转发
    • 黑名单
      • 配置ip清单
      • 开启黑名单
  • 配置参考
    • nginx限流和黑名单
    • hash_ip
    • frp转发获取真实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 "-" "-"

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

原因分析

查了一下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

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

		#listen       443 ssl ;
		#listen       443 ssl http2 proxy_protocol;
		listen       443 ssl proxy_protocol; # 以上http2根据实际情况添加,个别环境不加会正确
		real_ip_header proxy_protocol;
  		real_ip_recursive on;
  		set_real_ip_from 172.17.0.1;

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

效果:
如下没设置对之前打印docker网关地址,设置成功之后打印真实,切记listen 443 ssl http2 proxy_protocol;中http2择机设置

172.17.0.1 - - [30/Mar/2023:09:09:42 +0800] "GET / HTTP/1.1" 404 122 "-" "Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"
172.17.0.1 - - [30/Mar/2023:09:09:52 +0800] "GET /gateway/modules/iot/environment/data/list HTTP/2.0" 200 56 "-" "curl/7.84.0"
172.17.0.1 - - [30/Mar/2023:09:10:49 +0800] "POST /iot/open/third/alarm HTTP/1.1" 499 0 "-" "Go-http-client/1.1"
182.xx.2x4.xx5 - - [30/Mar/2023:09:11:27 +0800] "GET /gateway/modules/iot/environment/data/list HTTP/1.1" 200 67 "-" "curl/7.84.0"
182.xx.2x4.xx7 - - [30/Mar/2023:09:11:31 +0800] "POST /iot/open/third/alarm HTTP/1.1" 200 105 "-" "Go-http-client/1.1"

实战

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.xx.biz_nginx/frp.xx.biz.pem;
		ssl_certificate_key   /etc/nginx/ssl/frp.xx.biz_nginx/frp.xx.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;
		}    
		   
	}

多层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;
		}

黑名单

配置ip清单

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

#添加黑名单IP
deny 42.236.10.0/24;
# deny 58.59.219.11;
deny 180.163.220.0/24;

说明:

# 屏蔽单个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

开启黑名单

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

include blockips.conf;

配置参考

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

你可能感兴趣的:(开发组件,docker,nginx,tomcat)