如何玩转Nginx正反向代理
创始人
2025-07-01 10:41:42
0

一、场景

1、场景描述

  • 在客户的场景中,有两台测试服务windows server系统,无法访问外网。
  • 测试服务器中运行的业务程序,需要访问有几个公网域名。
  • 场景中还有一台代理服务器 ,它可以访问外网,也可以通两台测试服务器;

系统架构图如下。

2、需求

 两台不能访问外网的测试服务器里面的程序,需要访问外网的几个固定域名。

3、解决方法

  • 正向代理:代理服务器的nginx配置正向代理,为后面的测试服务器代理全部访问【限制条件是程序需要支持识别代理】。
  • 反向代理:代理业务程序所使用到的域名,使访问请求通过代理出去。

二、反向代理配置

1、公共域名http的反向代理

  • 反向代理公共域名,将内网服务器的http请求,代理转发至原本的域名中。
  • 例如 www.tyun.cn 代理转发至www.tyun.cn。

nginx配置

# cat default.conf 
server {
    listen 80;
    server_name _;
    
    location / {
        resolver 114.114.114.114;
        set $backend_host $host;  #将原始域名存储到变量中
        proxy_pass http://$backend_host$request_uri;  #使用变量保持原始域名
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

2、公共域名https的反向代理

  • 由于这次需要代理转发是其他公共域名,所以代理服务器没有这些公共域名的https证书,公共域名的IP也是会变动的,需要能够不提示证书问题,并且能够根据域名对应代理转发。
  • 所以通过4层转发,并且4层代理通过使用域名的形式,转发至原本的域名中。
  • 例如 www.tyun.cn代理转发至www.tyun.cn。

(1)nginx的ssl_preread

nginx的ssl_preread介绍:

Nginx 开始支持 SSL 的 ssl_preread 功能是在版本 1.9.0 中引入的。

ssl_preread 是 Nginx 的 Stream 模块中的一个指令,用于在 SSL 握手之前读取客户端发送的数据,通常用于提前获取客户端发送的信息,比如域名,从而根据这些信息做出代理或路由决策。这在反向代理和负载均衡的场景中特别有用。

以下是关于 ssl_preread 的详细描述:

功能介绍: ssl_preread 允许 Nginx 在 SSL/TLS 握手的早期阶段读取客户端发送的数据,包括 ClientHello 消息。这样做的目的是为了从握手的预读取数据中获取一些信息,以便在接下来的代理和路由过程中做出更明智的决策。

使用场景: ssl_preread 常用于以下场景:

  • 根据客户端发送的域名(SNI)将流量代理到不同的后端服务器。
  • 根据不同的协议或应用层协议(如 HTTP、SMTP、POP3 等)将流量路由到不同的后端服务器。

(2)nginx配置

安装nginx配置:

nginx编译安装需要添加特定模块。

--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module

nginx配置文件

这里需要业务系统中使用了几个域名就要配置几个upstream。

#user  nobody;
worker_processes  1;
#error_log  logs/error.log  info;
#pid        logs/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #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;
    
    include conf.d/*.conf;
}
#配置https反向代理
stream {
    map $ssl_preread_server_name $backend_hosthttps {
        www.tyun.cn                   tyun;
        www.tyun2.cn                   tyun2;
    }
    upstream tyun {
        server www.tyun.cn:443;
    }
    upstream tyun2 {
        server www.tyun2.cn:443;
    }
    server {
        listen 443;
        ssl_preread on;
        resolver 114.114.114.114;
        proxy_pass $backend_hosthttps;
        proxy_connect_timeout 5s;
        proxy_timeout 15s;
    }
}

(3)无外网win server服务器配置

需要配置hosts文件将域名指向代理服务器中。

C:\Windows\System32\drivers\etc\hosts。

192.168.1.100   www.tyun.cn
192.168.1.100   www.tyun2.cn

三、正向代理解决方案

1、正向代理存在的一些问题

正向代理配置之后,需要业务程序中本身支持读取系统中的代理配置。

2、配置正向代理

nginx正向代理,默认的nginx的无法支持https的访问,需要添加github上开源的proxy_connect模块,模块的链接如下 https://github.com/chobits/ngx_http_proxy_connect_module/。

编译安装nginx1.23 并添加开源的模块。

wget https://github.com/chobits/ngx_http_proxy_connect_module/archive/refs/heads/master.zip
unzip master.zip
yum install -y patch
#在nginx源码目录执行
cd /root/nginx-1.23.3
patch -p1 < /root/ngx_http_proxy_connect_module-master/patch/proxy_connect_rewrite_102101.patch
#nginx编译
./configure \
--prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_gzip_static_module \
--with-threads \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_realip_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--add-module=/root/ngx_http_proxy_connect_module-master


make && make install

配置nginx

server {
    listen                         8080;
    resolver                       114.114.114.114;
    proxy_connect;
    proxy_connect_allow            80 443;
    proxy_connect_connect_timeout  10s;
    proxy_connect_data_timeout     10s;
    location / {
        proxy_pass http://$host;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

3、无外网win server服务器配置

  • 配置完成后,经过验证服务器上的浏览器是可以正常代理http https类型都是没有问题的。
  • 业务系统无法走代理,因为程序不会自动使用系统设置的代理,而需要单独进行代理配置。

4、使用ptyhon获取系统代理配置示例

以下展示了一段Python的代码,来展示如何获取Windows server系统的代理,并使用该代理,访问公网。

import os
import requests
import winreg
# 获取 Windows 系统代理配置
internet_settings = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
proxy_enabled, _ = winreg.QueryValueEx(internet_settings, 'ProxyEnable')
proxy_server, _ = winreg.QueryValueEx(internet_settings, 'ProxyServer')
if proxy_enabled and proxy_server:
    proxies = {
        'http': 'http://' + proxy_server,
        'https': 'https://' + proxy_server,
    }
    os.environ['http_proxy'] = 'http://' + proxy_server
    os.environ['https_proxy'] = 'https://' + proxy_server
else:
    proxies = None
# 使用代理请求
response = requests.get('http://www.tyun.cn', proxies=proxies)
print(response.text)

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...