Nginx正向代理http(s)并禁止访问内网IP

424 阅读2分钟

nginx forward proxy http(s)

1. 下载nginx及ngx_http_proxy_connect_module

nginx: download

Releases · chobits/ngx_http_proxy_connect_module (github.com)

2. 编译安装(1.24版本)

  1. 解压nginx及ngx_http_proxy_connect_module
  2. 查找patch版本对应关系(select-patch
  3. 编译并安装
# 当前目录/app/nginx-1.24.0,nginx安装到/app/nginx_forward_proxy

# 找到ngx_http_proxy_connect_module的目录(/app/nginx-1.24.0/ngx_http_proxy_connect_module-0.0.5)
# 编译时添加ngx_http_proxy_connect_module:--add-module=/app/nginx-1.24.0/ngx_http_proxy_connect_module-0.0.5
# 如需steam 则还需添加
# --with-stream --with-stream_ssl_preread_module --with-stream_ssl_module 
# 根据select-patch对应关系patch

# 1. configure
./configure \
--prefix=/app/nginx_forward_proxy \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_auth_request_module \
--with-http_addition_module \
--with-http_realip_module \
--with-http_ssl_module \
--with-http_v2_module \
--add-module=/app/nginx-1.24.0/ngx_http_proxy_connect_module-0.0.5

# 2. patch
patch -p1 < \
/app/nginx-1.24.0/ngx_http_proxy_connect_module-0.0.5/patch/proxy_connect_rewrite_102101.patch

# 3. make
make && make install

3. 配置

配置文件: /app/nginx_forward_proxy/conf/nginx.conf

worker_processes  1;
events {
    worker_connections  512;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
     listen  8080;
     #http2 on;
     # 正向代理必须设置dns地址才能正常解析域名(如果要避免内网网站被代理,就需要设置外网的dns)
     resolver  114.114.114.114;
     proxy_connect; # ngx_http_proxy_connect_module
     # 允许的端口
     proxy_connect_allow          443 80;
     #proxy_connect_connect_timeout  10s;
     #proxy_connect_read_timeout     10s;
     #proxy_connect_send_timeout     10s;
     location / {
         if ($host ~ "^(?=127.0.0.1)|(?=localhost)|(?=10.\d{1,3}.\d{1,3}.\d{1,3})|(?=100.100.\d{1,3}.\d{1,3})|(?=172.(?=1[6789])|(?=2[0-9])|(?=3[01]).\d{1,3}.\d{1,3})") {
           return 403; #不允许代理环回和内网IP(127.0.0.1 localhost 10.0.0.0/8 100.100.0.0/16 172.16.0.0/11)
         }
         #完整传递URL
         proxy_pass $scheme://$host$request_uri;
         #proxy_set_header Host $host; #通常无需配置host
     }
    }
}

4. 启动

/app/nginx_forward_proxy/sbin/nginx

5. 测试

curl -v https://www.fastmock.site/mock/ -x 127.0.0.1:8080
*   Trying 127.0.0.1:8080...
* Connected to (nil) (127.0.0.1) port 8080 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to www.fastmock.site:443
> CONNECT www.fastmock.site:443 HTTP/1.1
> Host: www.fastmock.site:443
> User-Agent: curl/7.81.0
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 200 Connection Established
< Proxy-agent: nginx
< 
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=www.fastmock.site
*  start date: Dec 15 00:00:00 2023 GMT
*  expire date: Jan  8 23:59:59 2025 GMT
*  subjectAltName: host "www.fastmock.site" matched cert's "www.fastmock.site"
*  issuer: C=CN; O=TrustAsia Technologies, Inc.; CN=TrustAsia RSA DV TLS CA G2
*  SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /mock/ HTTP/1.1
> Host: www.fastmock.site
> User-Agent: curl/7.81.0
> Accept: */*
> 
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Server: nginx/1.17.8
< Date: Fri, 29 Dec 2023 06:57:28 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 23
< Connection: keep-alive
< X-Powered-By: Express
< Vary: Accept, Origin, Accept-Encoding
< Access-Control-Allow-Credentials: true
< Location: /
< Set-Cookie: connect.sid=s%3AEZ18bIKjudNmt1MDdgiJPk7Isxp_q3w2.wG6k9iHGk%2Fnnw8w7VFYrg0doKeY5ago3sMRgRra2kQw; Path=/; Expires=Fri, 29 Dec 2023 18:57:28 GMT; HttpOnly
< 
* Connection #0 to host (nil) left intact