最近在搭建一套内网开发环境时,遇到了一个典型的需求:需要让内网服务器能够安全地访问外部资源,同时又要避免直接暴露内网IP。经过多方调研,最终选择了Nginx作为正向代理服务器。这里记录下从源码编译安装Nginx 1.26.2并配置正向代理的完整过程,特别是如何集成ngx_http_proxy_connect_module这个关键模块。
选择Nginx做正向代理有几个明显优势:首先是性能卓越,单机轻松应对数千并发;其次是配置灵活,配合各种模块可以实现复杂需求;最重要的是稳定性好,我们线上业务已经跑了三年多没出过问题。这次选择的1.26.2是当前最新的稳定版,修复了之前版本的一些安全漏洞。
在开始之前,需要确保系统满足基本要求。我使用的是CentOS 7.9,理论上其他Linux发行版步骤类似。首先安装必要的开发工具和依赖库:
bash复制sudo yum groupinstall "Development Tools"
sudo yum install -y gcc gcc-c++ make pcre-devel zlib-devel openssl-devel
这里特别说明下各个依赖的作用:
注意:如果是生产环境,建议使用yum update先更新所有包到最新版本,避免已知漏洞影响安全性。
从官网下载Nginx源码包时,强烈建议通过https访问并验证校验和:
bash复制wget https://nginx.org/download/nginx-1.26.2.tar.gz
wget https://nginx.org/download/nginx-1.26.2.tar.gz.asc
# 导入官方签名密钥
gpg --keyserver pgp.mit.edu --recv-key ABF5BD827BD9BF62
gpg --verify nginx-1.26.2.tar.gz.asc nginx-1.26.2.tar.gz
解压源码包后进入目录:
bash复制tar -zxvf nginx-1.26.2.tar.gz
cd nginx-1.26.2
Nginx默认不支持CONNECT方法(HTTPS代理必需),需要额外安装ngx_http_proxy_connect_module模块:
bash复制wget https://codeload.github.com/chobits/ngx_http_proxy_connect_module/tar.gz/refs/tags/ngx_http_proxy_connect_module-0.0.7.tar.gz
tar -zxvf ngx_http_proxy_connect_module-0.0.7.tar.gz
这个模块的版本选择很重要,必须与Nginx版本兼容。0.0.7是目前支持1.26.x的最新稳定版。
由于模块需要对Nginx源码进行修改,需要先打补丁:
bash复制patch -p1 < ../ngx_http_proxy_connect_module-0.0.7/patch/proxy_connect_rewrite_1018.patch
如果遇到补丁失败,可能是版本不匹配。可以尝试手动修改源码,具体方法参考模块文档。
这是最关键的一步,配置不当可能导致后续功能缺失。我的完整配置如下:
bash复制./configure \
--prefix=/usr/local/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-stream \
--with-stream_realip_module \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-threads \
--add-module=../ngx_http_proxy_connect_module-0.0.7
几个重要选项说明:
执行编译和安装:
bash复制make -j$(nproc)
sudo make install
使用-j参数可以并行编译加快速度,nproc会自动获取CPU核心数。安装完成后,可以验证版本:
bash复制nginx -V
输出应该包含我们添加的模块信息。
编辑/etc/nginx/nginx.conf,在http块中添加:
nginx复制server {
listen 8888;
server_name proxy.example.com;
resolver 114.114.114.114 8.8.8.8 valid=300s;
resolver_timeout 10s;
proxy_connect;
proxy_connect_allow 443 80;
proxy_connect_connect_timeout 10s;
proxy_connect_read_timeout 20s;
proxy_connect_send_timeout 20s;
location / {
proxy_pass $scheme://$http_host$request_uri;
proxy_set_header Host $http_host;
proxy_buffers 256 4k;
proxy_max_temp_file_size 0;
proxy_connect_timeout 30;
}
}
关键参数解析:
为了安全考虑,应该限制代理的使用范围:
nginx复制location / {
allow 192.168.1.0/24;
deny all;
proxy_pass $scheme://$http_host$request_uri;
proxy_set_header X-Real-IP $remote_addr;
}
还可以添加认证:
nginx复制auth_basic "Proxy Authentication";
auth_basic_user_file /etc/nginx/.htpasswd;
使用htpasswd创建密码文件:
bash复制sudo htpasswd -c /etc/nginx/.htpasswd username
虽然Nginx会自动创建临时目录,但最好预先设置好权限:
bash复制sudo mkdir -p /var/cache/nginx/{client_temp,proxy_temp}
sudo chown -R nobody:nobody /var/cache/nginx
sudo chmod -R 755 /var/cache/nginx
创建/etc/systemd/system/nginx.service文件:
ini复制[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
然后启用服务:
bash复制sudo systemctl daemon-reload
sudo systemctl enable nginx
sudo systemctl start nginx
在/etc/nginx/nginx.conf的events块中添加:
nginx复制worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
根据服务器内存调整worker_processes,一般设置为CPU核心数。每个worker能处理的连接数由worker_connections决定。
建议将访问日志和错误日志分开:
nginx复制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 buffer=32k flush=5m;
error_log /var/log/nginx/error.log warn;
}
buffer和flush参数可以降低磁盘IO压力。
首先检查配置语法:
bash复制sudo nginx -t
然后测试HTTP代理:
bash复制curl -x http://proxy.example.com:8888 http://httpbin.org/ip
HTTPS代理测试:
bash复制curl -x http://proxy.example.com:8888 https://httpbin.org/ip
使用ab工具进行简单压力测试:
bash复制ab -n 1000 -c 50 -X proxy.example.com:8888 http://httpbin.org/get
观察Nginx的响应时间和错误率,如果出现大量错误可能需要调整worker_connections等参数。
Nginx自带的stub_status模块可以提供基础监控:
nginx复制location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
访问http://localhost/nginx_status可以看到:
code复制Active connections: 3
server accepts handled requests
100 100 200
Reading: 0 Writing: 1 Waiting: 2
可能原因及解决方案:
典型表现是客户端长时间等待后报超时错误:
nginx复制proxy_http_version 1.1;
proxy_set_header Connection "";
如果发现CONNECT方法不被支持:
除了基础的IP限制,还可以:
nginx复制proxy_connect_allow 443 80;
if ($http_host !~* "^(example.com|api.example.com)$") {
return 403;
}
nginx复制if ($request_method !~ ^(GET|HEAD|CONNECT)$) {
return 405;
}
建议记录更多安全相关字段:
nginx复制log_format security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time $upstream_response_time '
'$upstream_addr $upstream_status';
虽然代理本身是HTTP,但建议在Nginx和客户端之间启用HTTPS:
nginx复制server {
listen 443 ssl;
server_name proxy.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 其他代理配置...
}
可以配置多个上游代理服务器:
nginx复制upstream proxy_pool {
server proxy1.example.com:8888;
server proxy2.example.com:8888;
keepalive 32;
}
server {
location / {
proxy_pass http://proxy_pool;
}
}
对于静态资源可以启用缓存:
nginx复制proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=proxy_cache:10m inactive=60m;
server {
location / {
proxy_cache proxy_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
}
}
限制单个IP的连接数和速率:
nginx复制limit_conn_zone $binary_remote_addr zone=perip:10m;
server {
limit_conn perip 10;
limit_rate 1m;
}
配置logrotate定期切割日志:
bash复制sudo vim /etc/logrotate.d/nginx
内容如下:
code复制/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 nginx adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
使用Prometheus和Grafana监控关键指标:
保持Nginx更新到最新稳定版:
在实际运维中,我们发现这套代理架构能够稳定支持日均百万级的请求量。最关键的是合理配置worker_processes和worker_connections参数,避免内存溢出。另外,定期检查错误日志中的异常请求模式,可以帮助提前发现潜在的安全风险。