局域网中只有1台服务器可以访问外部网络,其他服务器如果要访问第三放地址只能通过代理器,其他服务器在/etc/hosts下手动添加解析条目,将第三放地址的域名都解析到这台代理服务器的ip。
> # cat /usr/local/nginx/conf/nginx.conf
```
user nginx nginx;
worker_processes auto;
error_log /usr/local/nginx/logs/error.log;
pid /usr/local/nginx/nginx.pid;
events {
use epoll;
worker_connections 65535;
}
stream {
# HTTP
map $ssl_preread_server_name $backend_http {
www.80.com www_80_com;
www.8080.com www_8080_com;
}
# HTTPS
map $ssl_preread_server_name $backend_https {
www.443.com www_443_com;
www.1443.com www_1443_com;
}
# 定义需要代理的各地址的 upstream
upstream www_80_com {
server www.80.com:80;
}
upstream www_8080_com {
server www.8080.com:8080;
}
upstream www_443_com {
server www.443.com:443;
}
upstream www_1443_com {
server www.1443.com:1443;
server {
listen 80;
resolver 192.168.1.110;
proxy_pass $backend_http;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
server {
listen 8080;
resolver 192.168.1.110;
proxy_pass $backend_http;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
server {
listen 443;
ssl_preread on;
resolver 192.168.1.110;
proxy_pass $backend_https;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
server {
listen 1443;
ssl_preread on;
resolver 192.168.1.110;
proxy_pass $backend_https;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
}
```
> nginx stream 代理配置解读
这个配置文件是Nginx的`stream`模块配置,主要用于四层(TCP/UDP)代理和负载均衡功能,而不是通常的七层(HTTP)代理。
## 配置结构分析
### 1. 基础配置部分
```nginx
user nginx nginx;
worker_processes auto;
error_log /usr/local/nginx/logs/error.log;
pid/usr/local/nginx/nginx.pid;
events {
use epoll;
worker_connections 65535;
}
```
- 以`nginx`用户和组运行
- 自动设置worker进程数量
- 错误日志和pid文件路径
- 事件模块使用epoll高效模型,每个worker支持65535个连接
### 2. Stream模块核心功能
#### 2.1 域名映射(map指令)
```nginx
# HTTP
map $ssl_preread_server_name $backend_http {
www.80.com www_80_com;
www.8080.com www_8080_com;
}
# HTTPS
map $ssl_preread_server_name $backend_https {
www.443.com www_443_com;
www.1443.com www_1443_com;
}
```
- 创建了两个映射表,根据SNI(Server Name Indication)信息将域名映射到对应的upstream
- `$ssl_preread_server_name`是Nginx在SSL握手前读取的客户端请求的服务器名称
- 第一个映射处理HTTP流量(非加密),第二个处理HTTPS流量(加密)
#### 2.2 Upstream定义
```nginx
upstream www_80_com {
server www.80.com:80;
}
upstream www_8080_com {
server www.8080.com:8080;
}
upstream www_443_com {
server www.443.com:443;
}
upstream www_1443_com {
server www.1443.com:1443;
}
```
- 定义了4个后端服务器组
- 每个upstream对应一个特定的域名和端口组合
#### 2.3 服务器监听配置
**HTTP代理服务器(端口80):**
```nginx
server {
listen 80;
resolver 192.168.1.110;
proxy_pass $backend_http;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
```
- 监听80端口(HTTP)
- 使用DNS解析器192.168.1.110
- 根据`$backend_http`映射表转发流量
- 各种超时设置为300秒
**HTTP代理服务器(端口8080):**
```nginx
server {
listen 8080;
resolver 192.168.1.110;
proxy_pass $backend_http;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
```
- 类似80端口配置,但监听8080端口
**HTTPS代理服务器(端口443):**
```nginx
server {
listen 443;
ssl_preread on;
resolver 192.168.1.110;
proxy_pass $backend_https;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
```
- 监听443端口(HTTPS)
- 启用`ssl_preread`以获取SNI信息
- 根据`$backend_https`映射表转发流量
**HTTPS代理服务器(端口1443):**
```nginx
server {
listen 1443;
ssl_preread on;
resolver 192.168.1.110;
proxy_pass $backend_https;
proxy_connect_timeout 300s;
proxy_timeout 300s;
proxy_next_upstream_timeout 300s;
}
```
- 类似443端口配置,但监听1443端口
## 功能总结
这个配置实现了一个**基于SNI的四层(TCP)代理服务器**,主要功能包括:
1. **透明代理**:根据客户端请求的域名将流量转发到不同的后端服务器
2. **多端口支持**:同时支持HTTP(80,8080)和HTTPS(443,1443)流量的代理
3. **域名路由**:使用SNI信息在SSL握手前就确定后端服务器
4. **TCP负载均衡**:虽然每个upstream只有一个服务器,但可以扩展为多服务器实现负载均衡
这种配置常用于:
- 需要基于域名的TCP层路由
- SSL/TLS终止前的流量转发
- 多域名共享同一IP和端口的场景
- 需要透明代理而不修改数据包内容的场景
注意:这不是传统的HTTP反向代理,而是在更底层的TCP/UDP层工作的代理。
> ssl_preread 配置的作用是什么 ?
`ssl_preread` 是 Nginx 在 **Stream 模块(四层代理)** 中用于 **SNI(Server Name Indication)解析** 的关键指令,它使得 Nginx 可以在不解密 TLS/SSL 流量的情况下,提前读取客户端请求的域名信息,从而进行路由决策。
---
## **`ssl_preread` 的作用**
1. **读取 SNI 信息**
- 在 TLS/SSL 握手阶段,客户端(如浏览器)会发送 `SNI` 扩展字段,告诉服务器它要访问的域名(如 `www.www.example.com`)。
- `ssl_preread` 让 Nginx 在不解密 TLS 数据的情况下,提前读取这个 SNI 信息。
2. **基于域名的 TCP 层路由**
- 结合 `map` 指令,Nginx 可以根据 `$ssl_preread_server_name` 变量将流量代理到不同的后端服务器(如 `upstream`)。
- 例如:
```nginx
map $ssl_preread_server_name $backend {
www.example.com backend1;
www.test.com backend2;
}
```
这样,访问 `www.example.com:443` 的流量会被代理到 `backend1`,而 `www.test.com:443` 的流量会被代理到 `backend2`。
3. **支持 HTTPS 透明代理**
- 传统的 HTTP 反向代理(`http` 模块)可以解析 `Host` 头来路由请求,但 HTTPS 流量是加密的,Nginx 无法直接读取 `Host` 头。
- `ssl_preread` 允许 Nginx 在不解密 TLS 的情况下,仅读取 SNI 信息,实现类似 HTTP 代理的路由功能。
4. **提高性能(不解密 TLS)**
- 由于 Nginx 只是读取 SNI,而不进行 TLS 解密,它的性能比完整的 TLS 终止(解密后再代理)更高,适用于透明代理场景。
---
## **`ssl_preread` 的典型应用场景**
1. **多域名 HTTPS 代理**
- 多个 HTTPS 域名(如 `a.com:443` 和 `b.com:443`)共享同一个 IP 和端口,Nginx 根据 SNI 将流量转发到不同的后端服务器。
2. **CDN 或 LB(负载均衡)**
- 在四层负载均衡中,基于 SNI 路由不同的 TLS 流量到对应的后端服务。
3. **透明代理(如上网工具)**
- 某些代理工具利用 SNI 信息进行流量分类和转发。
4. **端口复用**
- 例如,让 `:443` 同时代理 HTTP/3 (QUIC)、HTTPS、Trojan 等不同协议,通过 SNI 区分。
---
## **示例配置**
```nginx
stream {
# 定义 SNI 到 upstream 的映射
map $ssl_preread_server_name $backend {
www.example.com backend_https01;
www.test.com backend_https02;
}
# 定义后端服务器
upstream backend_https01 {
server 1.2.3.4:443;
}
upstream backend_https02 {
server 5.6.7.8:443;
}
# 监听 443,启用 ssl_preread
server {
listen 443;
ssl_preread on;
proxy_pass $backend;
}
}
```
- 当客户端访问 `www.example.com:443` 时,Nginx 会读取 SNI,发现是 `www.example.com`,然后代理到 `backend_https01`(1.2.3.4:443)。
- 访问 `www.test.com:443` 则代理到 `backend_https02`(5.6.7.8:443)。
---
## **`ssl_preread` vs `ssl`(TLS 终止)**
| 特性| `ssl_preread`(SNI 路由) | `ssl`(TLS 终止) |
|--------------|--------------------------|------------------|
| **是否解密 TLS** | ❌ 不解密,仅读取 SNI | ✅ 解密 TLS |
| **适用场景** | 透明代理、四层 LB | HTTPS 反向代理 |
| **性能** | 更高(不解密) | 较低(需解密) |
| **能否修改内容** | ❌ 不能(TCP 层) | ✅ 能(HTTP 层) |
---
## **总结**
- `ssl_preread` 主要用于 **在不解密 TLS 的情况下读取 SNI**,实现基于域名的四层代理。
- 适用于 **HTTPS 透明代理、多域名路由、CDN、科学上网工具** 等场景。
- 相比完整的 TLS 终止(`ssl`),它的性能更高,但不能修改加密内容。
如果你的需求是 **"不解密 TLS,但要根据域名路由"**,`ssl_preread` 是最佳选择!
800

被折叠的 条评论
为什么被折叠?



