使用Nginx做正向代理
https://github.com/chobits/ngx_http_proxy_connect_module
HTTP/HTTPS代理服务器
nginx是一个反向代理工具,其实它是不支持正向代理的,如果你真的需要一个正向代理服务器,你应该去用squid。
nginx做正向代理只做简单的转发,也没有设计像squid一样的缓存之类的正向代理的功能。 有L4和L7两种部署方式,L7有些像squid, 但性能可能不大好, 也会有些奇怪的问题,比如网页某一次访问的时候打不开, 刷新一下就又好了。 L4的使用就更奇怪了, nginx会监听某一个端口,比如443或者80, 然后客户机通过DNS解析的方式,把要代理的域名解析到代理服务器,然后由代理服务器转发。
HTTP CONNECT (L7 方案)
Nginx设计出来是做反向代理的,所以它天生不支持HTTP CONNECT这个Method, github上有个大哥写了这么个插件 https://github.com/chobits/ngx_http_proxy_connect_module,需要通过编译的方式来安装nginx.
-
下载nginx源码
-
下载ngx_http_proxy_connect_module源码
-
根据nginx的版本patch connect module中带的指定patch文件,这在github的Readme中有说明,比如本文举例子用的nginx-1.16.1对应的是 proxy_connect_rewrite_101504.patch
cd /root git clone https://github.com/chobits/ngx_http_proxy_connect_module wget http://nginx.org/download/nginx-1.16.1.tar.gz tar zxvf nginx-1.16.1.tar.gz cd nginx-1.16.1 patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch
-
编译时指定connect module的源码位置
#准备CentOS下的编译环境 yum update yum -y install gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel # ubuntu下的编译环境 apt update apt install build-essential libpcre3 libpcre3-dev libssl-dev zlib1g-dev libgd-dev #添加用户和组 cd /root/nginx-1.16.1 ./configure \ --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-http_realip_module \ --with-threads \ --add-module=/root/ngx_http_proxy_connect_module ## 如果已经有nginx环境了,可以不执行make install, make之后把./objs/nginx二进行文件拷贝出来就能用, 执行nginx -V可以显示编译的参数 make && make install
-
nginx.conf 的配置样例
server { listen 8001; # dns resolver used by forward proxying resolver 114.114.114.114; # forward proxy for CONNECT request proxy_connect; proxy_connect_allow 80 443; proxy_connect_connect_timeout 10s; proxy_connect_read_timeout 10s; proxy_connect_send_timeout 10s; # forward proxy for non-CONNECT request location / { proxy_pass http://$host; proxy_set_header Host $host; } }
- 测试
在局域网中找另外一台机器,执行下面的命令, 把http://192.168.1.100:8001配置成代理,然后打开网页。 此时可以使用tail -f 观察nginx的access.log日志,可以看到访问的日志。
NGINX Stream (L4方案)
在L4方案中, nginx可以做透明代理, nginx需要的编译模块和L7的不一样, 不需要下载connect module,只需要下载nginx的源码,并使用以下
- 编译参数
./configure \
--prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-threads \
--with-stream \
--with-stream_ssl_preread_module \
--with-stream_ssl_module \
- https 代理配置 nginx.conf
stream {
resolver 114.114.114.114;
server {
listen 443;
ssl_preread on;
proxy_connect_timeout 5s;
proxy_pass $ssl_preread_server_name:$server_port;
}
}
- http代理配置 nginx.com
server {
listen 80;
location / {
resolver 8.8.8.8;
proxy_pass http://$http_host$uri$is_args$args;
}
}
- DNS劫持
使用这个“代理”需要用DNS解析来配合使用, 把需要走代理的域名解析到nginx代理所在的服务器地址。PS: 这个用法好奇怪 ,不知道在啥环境下能用起来。比如说, 我通过本地的DNS或者host文件,把www.baidu.com 这个域名指向代理服务器的地址, 把我所有想通过代理走的地址都解析到代理服务器的地址去。 当我通过浏览器去打开https://www.baidu.com:443的时候, 请示就会被指向https://代理服务器地址:443去。
配置http和https的代理需要监听80和443两个端口, https的配置会有点不一样,需要ssl_preread_module。 http的代理几乎就是反向代理的配置。
我没有想好具体的应用场景, 我猜想的一个可能的使用场景,比如某个网站如果只允许从一个固定的IP地址A访问, 此时有个在公网IP B的用户也想要访问, 就可以用这个L4的代理转发一下?
- 测试
在局域网的另外一台计算机, 配置一个host文件记录,比如说
192.168.1.100 baidu.com www.baidu.com
然后打开浏览器,是否能正常打开百度的首页。 然后再把nginx服务停掉,看看是不是就不能正常打开baidu首页了。
注册nginx到Systemd
vi /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target