最近想要实现蜜罐运维端口的跨区转发(A区,C区不通,走B区中转实现 A到B到C的运维)。看完官方文档和几篇不错的博客后,现小结记录,方便以后快速配置Nginx转发相关功能。
Nginx是一款轻量化但功能丰富的中间件,可作为HTTP服务器,也可作为反向代理服务器,邮件服务器。它不仅支持FastCGI、SSL、Virtual Host、URL Rewrite、Gzip等功能,还可以结合openresty等丰富的第三方扩展实现云waf等等各种高级操作。
nginx配置文件默认位置/etc/nginx/nginx.conf
,一般结构如下
... # 全局设置
events { # events块,用于设置nginx工作模式,配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
....
}
http { # http块,可以包含多个server和upstream
....
upstream back { # 负载均衡上游服务器,后面可以通过变量back调用
.....
}
server { # 主机配置:主要包含监听端口,路由选择等
....
location / { # location,路由配置
....
}
}
这是目前网上各种博客讲的最多的东西,做WEB类的负载均衡和网页转发用的比较多,能搜到实例非常多。主要是配置http块
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式
access_log log/access.log myFormat; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。
upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
error_page 404 https://www.baidu.com; #错误页
server {
keepalive_requests 120; #单连接请求上限次数。
listen 4545; #监听端口
server_name 127.0.0.1; #监听地址
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index vv.txt; #设置默认页
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
}
}
nginx最常见的用法是转发七层的web服务。从1.9.0之后的版本,nginx加入stream模块,支持四层协议TCP的转发,1.9.3之后支持UDP的转发。其实有了这个功能之后其实完全可以使用stream模块转发HTTP,放弃http模块。
需要注意的是,现在通过yum安装应该是有stream模块的,如果通过源码安装,可能编译的时候要加上stream模块
./configure --prefix=/usr/local/nginx --with-stream
make && make install
下面是样例配置
stream {
# 可以按需求配置日志
log_format proxy '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received"
"$upstream_connect_time"';
access_log /var/log/nginx/tcp-access.log proxy ;
# tcp转发的上游
upstream backend {
hash $remote_addr consistent;
server 127.0.0.1:12346 weight=5;
server 127.0.0.1:12347 max_fails=3 fail_timeout=30s;
server 127.0.0.1:12348 max_fails=3 fail_timeout=30s;
}
# udp转发的上游
upstream dns { # 多台DNS server HA
server 17.61.29.79:53;
server 17.61.29.80:53;
server 17.61.29.81:53;
server 17.61.29.82:53;
}
# tcp转发的虚拟server
server {
listen 12345; # 监听端口
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass backend; # 转发12345端口到上游的backend
}
# udp转发的虚拟server
server {
listen 127.0.0.1:53 udp; # 监听端口
proxy_responses 1; # nginx等待的回包数量
proxy_timeout 20s;
proxy_pass dns; # 转发端口
}
虽然stream模块是转发四层的,http模块转发七层,存在包含关系。但其实两者同时配置是可以正常工作的。stream块和http块是允许并列存在。如下配置为把7003端口转发到 172.33.1.22的ssh服务(port22)上,同时把本地7002端口转发到 www.fucguigui.com的80口。
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
stream {
upstream lssh{
server 172.33.1.2:22;
}
server {
listen 7003;
proxy_pass lssh;
# 也支持socket
# proxy_pass unix:/var/lib/mysql/mysql.socket;
}
}
http {
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 /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream fucguigui{
server www.fucguigui.com;
}
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 7002 default_server;
listen [::]:7002 default_server;
server_name _;
# root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://fucguigui;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
nginx -t
检查策略文件可以通过,但是启动服务的时候会失败,注意检查。proxy_response
参数的话,短时间转发大量udp的时候会占用连接,造成worker_connections are not enough
,具体可参考sof 上老哥的描述。如果是转发dns,设置proxy_response 1
即可,如果是是转发日志这种设置proxy_response 0
就可以了。-----------20210521更新----------------------
有时候nginx配置完转发,tcp仍然转发不成功,查看nginx的error.log 显示 Permission denied) while connecting to upstream。
其实ngx转发是成功的,只不过被selinux拦截了。允许httpd发起连接即可
setsebool -P httpd_can_network_connect 1
Nginx 配置详解 (其实并不详,讲转发http的)
Nginx中文文档 (较详细,但完整例子零散)