反向代理原理和服务转发实现方式

反向代理原理和服务中转访问实现

反向代理是客户端通过中间代理服务器中转访问原始服务器技术,其工作原理是通过中间服务器转发客户端请求到后端服务器并返回后端服务器响应到客户端,对用户客户端隐藏真实服务器信息(即客户端用户只知道中间服务器代理后端服务器服务后的访问地址,不知道原始服务地址),下面介绍反向代理工作原理、功能优势、实现方案、应用场景:

一、工作原理

‌1、请求拦截与转发

客户端向反向代理服务器发起TCP(HTTP、HTTPS、WebSocket、SSH、RDP等)、UDP等请求,反向代理服务器根据路由、转发规则将请求转发至匹配的后端服务器,并将后端服务的响应返回给客户端。

‌2、隐藏后端架构

反向代理屏蔽了后端服务器的真实IP(域名)和拓扑结构,外部用户无法直接访问内网服务器,仅能通过代理服务器交互。

3、跨网络访问支持

如果您有独立固定公网IP(域名),可通过反向代理服务器与内网私有IP服务器结合(借助路由器端口映射、Nginx等反向代理工具),实现公网用户通过公网IP(域名)+端口访问内网资源,例如对外暴露内网的OA等Web服务。

如果企业或个人内网没有公网IP和端口,也可以通过在内网服务器和其他带独立外网IP(域名)+端口的云服务器部署内网穿透工具中转方式反向代理到外网访问,比如frp、nps或者我上一篇提到的jrp-nat-vertx:

jrp-nat-vertx

zoyation,公众号:java-tonyjava内网穿透工具jrp-nat-vertx

二、功能优势

‌1、安全性‌:作为网络统一出入口,防止直接扫描攻击,支持集成WAF过进行安全控制(WAF:Web Application Firewall即Web应用防火墙,是一种专为Web应用程序设计的安全防护工具,通过监控、过滤和分析HTTP/HTTPS流量,识别并拦截恶意请求,从而保护Web应用免受SQL注入、跨站脚本(XSS)、跨站请求伪造(CSRF)等常见网络攻击),后端HTTP服务反向代理成HTTPS服务访问增加访问的安全性等。

‌2、性能优化‌:缓存静态资源(页面、图片、js、css等)、SSL卸载(代理服务器上统一对HTTPS加解密)减轻后端负载。

3、负载均衡‌:通过轮询、随机、最少连接、响应速度、IP哈希等算法分配请求至多台后端服务器。

三、服务中转实现方案

当有把多个服务通过统一中转服务器(IP/域名)作为统一出入口暴露出去时,可采用"借助三方工具"和"使用系统自带工具"两种方案,根据实际需求选择对应实现方案。

1、借助三方工具

除了统一进行服务中转还需要做额外安全控制等转发处理时,可通过nginx、apache、caddy等第三方工具对已有服务进行反向代理实现,灵活适配Web应用、API网关等场景;java微服务应用可通过Spring Cloud Gateway(作为微服务入口,Gateway统一处理跨域、鉴权和监控,简化客户端与后端服务的交互复杂度);也可以自己开发工具。

借助nginx配置示例

基础配置

监听80端口并将请求转发至后端服务(如本地8080端口),同时传递客户端原始信息(如ip):

复制代码
server {
    listen 80;
    location / {
        proxy_pass http://192.168.1.89:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

负载均衡配置‌

使用nginx的upstream模块定义多台后端服务器,并指定调度算法(如加权轮询):

复制代码
upstream backend {
    server backend1.example.com weight=3;
    server backend2.example.com;
}
server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}

高级功能‌

  1. 动静分离‌:将静态资源请求与动态请求路由至不同服务器。

  2. IP透传 ‌:通过多级代理头(如X-Forwarded-For)传递原始客户端IP。

  3. 其他:协议升级为websocket、返回内容替换、

2、自己开发工具

比如可以使用vert.x开发HTTP反向代理工具,示例如下:

复制代码
!--maven添加依赖包-->
<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-web-proxy</artifactId>
  <version>5.0.4</version>
</dependency>
//java示例代码
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
HttpServer proxyServer = vertx.createHttpServer();
HttpClient proxyClient = vertx.createHttpClient();
Router proxyRouter = Router.router(vertx);
// 代理1
HttpProxy httpProxy1 = HttpProxy.reverseProxy(proxyClient);
	httpProxy1.origin(7070, "192.168.1.88");
// 代理2
HttpProxy httpProxy2 = HttpProxy.reverseProxy(proxyClient);
	httpProxy2.origin(6060, "192.168.1.89");
//路由路径1配置
	proxyRouter.route(HttpMethod.GET, "/foo").handler(ProxyHandler.create(httpProxy1));
//路由路径2配置
	proxyRouter.route(HttpMethod.GET, "/bar").handler(ProxyHandler.create(httpProxy2));
	proxyServer.requestHandler(proxyRouter);
	proxyServer.listen(80);
}

上面示例实现:

http://192.168.1.88:7070/foo和http://192.168.1.89:6060/bar两个接口反向代理到80端口。

参考:https://vertx.io/docs/vertx-web-proxy/java/

3、使用系统自带工具进行转发

Linux、Windows、maceOS等系统都有对应自带端口转发工具,直接转发需求可以考虑使用。

linux系统使用防火墙工具示例

在Linux系统中,通过iptables或firewalld这样的防火墙管理工具来实现简单的端口转发正向代理,firewalld工具实现端口转发(正向代理)方式如下:

‌查看当前区域‌(可选,了解配置):

复制代码
sudo firewall-cmd --list-all

‌添加端口转发规则‌:

比如你想将所有到达本机端口8080的流量转发到内网IP地址192.168.1.89:80:

复制代码
sudo firewall-cmd --zone=public --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=192.168.1.89

‌重新加载firewalld配置‌(使改动生效):

复制代码
sudo firewall-cmd --reload

windows系统使用netsh示例

在Windows系统中设置端口转发主要通过内置的netsh命令实现,需以管理员权限运行命令提示符或PowerShell,并确保IP Helper服务已启用。‌核心步骤包括添加转发规则、验证配置及处理防火墙设置,仅支持TCP协议。

  • 启用IP Helper服务

端口转发依赖Windows的IP Helper服务,需先启用:

1.修改‌‌注册表:

复制代码
reg add HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters /v IPEnableRouter /D 1 /f

或将注册表项HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter值设为1。‌‌

‌2.启动Routing服务‌:

复制代码
sc config RemoteAccess start= auto
sc start RemoteAccess
  • 配置端口转发规则

使用netsh interface portproxy命令操作:

‌1.添加规则‌:

复制代码
netsh interface portproxy add v4tov4 listenaddress=<本地IP> listenport=<本地端口> connectaddress=<目标IP> connectport=<目标端口> protocol=tcp

示例:将本地所有IP的80端口转发到192.168.1.100的8080端口:

复制代码
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=80 connectaddress=192.168.1.100 connectport=8080
  1. ‌查看规则‌:

执行netsh interface portproxy show all验证配置。‌‌

  1. ‌删除规则‌:

    netsh interface portproxy delete v4tov4 listenaddress=<本地IP> listenport=<本地端口>

或reset清除所有规则。‌‌

  • 防火墙与路由设置

‌放行端口‌:在Windows Defender防火墙高级设置中创建入站规则,允许本地端口的TCP流量。‌‌

‌启用路由转发‌(跨网络场景),执行:

复制代码
netsh interface ipv4 set subinterface "网卡名" forwarding=enabled

macOS通过内置的pf设置示例

在 macOS 系统中配置端口转发主要通过内置的 pf(Packet Filter)防火墙工具实现,以下是具体方法和注意事项:

  • 基础配置方法

1‌.编辑 /etc/pf.conf 文件‌

在 rdr-anchor "com.apple/*" 下方添加转发规则,例如将本地 80 端口转发到 8080 端口:

复制代码
rdr on lo0 inet proto tcp from any to 127.0.0.1 port 80 -> 127.0.0.1 port 8080

保存后需重新加载配置:

复制代码
sudo pfctl -f /etc/pf.conf
sudo pfctl -e

2‌.使用独立锚点文件‌

可在 /etc/pf.anchors/ 目录下创建自定义规则文件(如 com.portforward),内容示例:

复制代码
rdr pass on en0 inet proto tcp from any to any port 9999 -> 127.0.0.1 port 8087

然后在 /etc/pf.conf 中引用该锚点文件:

复制代码
rdr-anchor "portforward"
rdr-anchor "portforward"

通过如下命令验证语法正确性:

复制代码
sudo pfctl -vnf /etc/pf.anchors/com.portforward
  • 高级配置与注意事项

‌1.启用 IP 转发‌

需确保 IPv4 转发功能开启:

复制代码
sudo sysctl -w net.inet.ip.forwarding=1

可通过 sysctl -a | grep forward 检查状态。

2‌.多网卡适配‌

规则需根据实际网络接口(如 lo0、en0)调整,可通过 ifconfig -a 查看接口名称。

‌3.开机自启‌

修改 /etc/pf.conf 后,规则会随系统启动自动加载。

四、常见应用场景

隐藏服务‌:保护内网API、数据库、SSH等远程桌面,简单场景可通过系统自带工具端口转发实现。

跨域处理‌:配置CORS头解决前端跨域问题,通过nginx等第三方工具实现。

高可用架构‌:结合健康检查实现故障自动切换,通过nginx、gateway或者其他第三方工具实现。