部署架构
浏览器–>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