[Linux] 开启本地网络转发功能(IPv4)

警告

  • 在配置 iptables/nftables 时,如果不小心清空了所有规则并且默认策略是 DROP,你可能会把自己关在服务器外面(尤其是通过 SSH 连接时)。务必谨慎。
  • 在生产环境中,建议使用 iptables-persistent 或 nftables 的持久化配置服务,并先在本地测试。
    如果只是希望简单的做流量转发的话,其实直接使用ssh -D 开一个socks5隧道,配合proxychain的方式最省事,不需要折腾Linux的流量转发

01 原理

IPTables和NFTables等流量防火墙工具,通过设置SNAT/MASQUERADE 和 DNAT 规则,可以达到用于修改、过滤和转发数据包的目的。

  • SNAT (Source NAT) / MASQUERADE:
    修改数据包的源地址
    当内网客户端通过你的“代理”访问外网时,你需要将客户端的私有 IP 地址“伪装”成“代理”服务器的公网 IP,这样外网服务器才会把回复包发回给你的“代理”。

  • DNAT (Destination NAT):
    修改数据包的目标地址
    常用于端口转发,将发送到“代理”某个端口的数据,转发到内部另一台机器的指定端口。

02 网关模式

2.1 简介

客户端将网关设置为你的 Linux 服务器。
客户端的流量都经过你的Linux服务器,由它转发到互联网。
适用于为整个子网提供互联网出口。

2.2 开启Linux转发功能

临时启用(重启失效)

# 开启 IPv4 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 开启 IPv6 转发(如果需要)
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding

配置系统conf(持久生效)

# 写入sysctrl的conf
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf
# 使conf生效
sysctl -p

2.3 使用iptables方法

# 1. 清空现有规则(谨慎操作!如果是生产环境,请勿直接执行)
# iptables -F
# iptables -t nat -F
# 2. 设置默认策略(可选,同样是谨慎操作)
# iptables -P FORWARD DROP
# 3. 允许已建立的连接和相关连接通过
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 4. 允许从内网接口(eth1)到公网接口(eth0)的转发
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
# 5. 在 NAT 表的 POSTROUTING 链上添加 MASQUERADE 规则
#    这条规则是关键!它将来自内网(10.0.0.0/24)的流量源IP伪装成eth0的IP
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
# 6. (可选)允许转发链的入站流量
# iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

2.4 使用NFTables配置

创建新的配置文件 /etc/nftables.conf

#!/usr/sbin/nft -f

# 定义 NAT 表 - 用于网络地址转换
# inet 表示同时支持 IPv4 和 IPv6
table inet nat {
        # 创建 postrouting 链 - 处理出站数据包的地址转换
        chain postrouting {
                # 链类型:nat(网络地址转换)
                # 钩子点:postrouting(数据包离开系统前的最后处理阶段)
                # 优先级:srcnat(源地址转换优先级,值为 -100)
                # 策略:默认接受所有数据包
                type nat hook postrouting priority srcnat; policy accept;

                # MASQUERADE 规则:
                # - 对从 eth0 接口出站的数据包进行源地址伪装
                # - 将内网设备的私有 IP 转换为 eth0 的公网 IP
                # - 自动处理连接跟踪,适用于动态 IP 环境(如 DHCP)
                oifname "eth0" masquerade
        }
}

# 定义过滤器表 - 用于数据包过滤
# inet 表示同时支持 IPv4 和 IPv6
table inet filter {
        # 创建 forward 链 - 处理经过本机转发的数据包
        chain forward {
                # 链类型:filter(数据包过滤)
                # 钩子点:forward(转发数据包的处理阶段)
                # 优先级:filter(过滤优先级,值为 0)
                # 策略:默认丢弃所有转发数据包(安全默认策略)
                type filter hook forward priority filter; policy drop;

                # 接受已建立连接和相关连接的数据包
                # - established:已建立的连接
                # - related:与现有连接相关的新连接(如 FTP 数据连接)
                ct state established,related accept

                # 允许从内网到外网的转发:
                # - iifname "eth1": 输入接口为 eth1(通常代表内网接口)
                # - oifname "eth0": 输出接口为 eth0(通常代表外网接口)
                # 这意味着允许内网设备通过本机访问互联网
                iifname "eth1" oifname "eth0" accept
        }
}

加载nft配置

nft -f /etc/nftables.conf
  • MASQUERADE 动作会自动使用出口 eth0 的 IP 作为源地址,无需手动指定。
  • FORWARD 链的规则确保了只有合法的流量才能被转发。

03 端口转发

客户端直接连接到你的 Linux 服务器的某个端口。
服务器将此连接转发到指定的目标服务器和端口。
适用于暴露内网特定服务,或做简单的 TCP/UDP 中继。

3.1 开启IP转发功能

临时启用(重启失效)

# 开启 IPv4 转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 开启 IPv6 转发(如果需要)
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding

配置系统conf(持久生效)

# 写入sysctrl的conf
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' >> /etc/sysctl.conf
# 使conf生效
sysctl -p

3.2 配置IPTables的DNAT规则

# 1. 在 PREROUTING 链进行目标地址转换 (DNAT)
#    将访问 192.0.2.10:8080 的包,目标改为 10.0.0.200:80
iptables -t nat -A PREROUTING -d 192.0.2.10 -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.200:80

# 2. 在 POSTROUTING 链进行源地址转换 (SNAT)
#    让回来的包知道要发回给原始的请求者。对于转发,通常用 MASQUERADE 也可以。
iptables -t nat -A POSTROUTING -p tcp -d 10.0.0.200 --dport 80 -j MASQUERADE

# 3. 允许转发到目标地址的特定端口
iptables -A FORWARD -d 10.0.0.200 -p tcp --dport 80 -j ACCEPT

3.3 使用NFTables配置

在 /etc/nftables.conf 中添加:

# 定义 IPv4 专用的 NAT 表(只处理 IPv4 流量)
table ip nat {
        # 创建 prerouting 链 - 处理入站数据包的目标地址转换
        chain prerouting {
                # 链类型:nat(网络地址转换)
                # 钩子点:prerouting(数据包进入系统后最早的处理阶段)
                # 优先级:dstnat(目标地址转换优先级,值为 -100)
                # 策略:默认接受所有数据包
                type nat hook prerouting priority dstnat; policy accept;

                # DNAT 规则:端口转发
                # - 条件:目标 IP 为 192.0.2.10 且目标端口为 8080 的 TCP 数据包
                # - 动作:将目标地址修改为 10.0.0.200:80
                # 效果:将公网 IP 192.0.2.10 的 8080 端口转发到内网服务器 10.0.0.200 的 80 端口
                ip daddr 192.0.2.10 tcp dport 8080 dnat to 10.0.0.200:80
        }

        # 创建 postrouting 链 - 处理出站数据包的源地址转换
        chain postrouting {
                type nat hook postrouting priority srcnat; policy accept;

                # MASQUERADE 规则:
                # - 对从 eth0 接口出站的数据包进行源地址伪装
                # - 将内网设备的私有 IP 转换为 eth0 的公网 IP
                oifname "eth0" masquerade
        }
}

# 定义过滤器表 - 用于数据包过滤(同时支持 IPv4 和 IPv6)
table inet filter {
        # 创建 forward 链 - 处理经过本机转发的数据包
        chain forward {
                type filter hook forward priority filter; policy drop;

                # 接受已建立连接和相关连接的数据包
                # 确保双向通信的正常进行
                ct state established,related accept

                # 允许转发到内网 Web 服务器的流量:
                # - 条件:目标 IP 为 10.0.0.200 且目标端口为 80 的 TCP 数据包
                # - 这专门允许外部用户访问内网 Web 服务器的流量通过
                ip daddr 10.0.0.200 tcp dport 80 accept
        }
}

04 两种场景的区别

4.1 网关模式

  • 本机直接作为client的网关
  • client的所有网络流量都经过本机
  • client无感知
  • 适用于client整个网络出口,透明过滤

4.2 端口转发模式

  • 需要配置代理地址和端口
  • 只转发特定端口
  • 客户端需要知道代理存在
  • 适用简易的tcp代理

05 为什么需要专业代理软件

  • 协议理解
    像 Squid (HTTP)、HAProxy (TCP/HTTP) 能理解应用层协议,实现缓存、内容过滤、负载均衡、健康检查等。
  • 用户认证
    可以对用户进行认证和授权。
  • 日志记录
    更详细的访问日志和流量分析。
  • 性能优化
    高级连接池、缓存策略等。
  • 复杂协议支持
    例如 SOCKS5 代理,需要协议握手,这是纯内核转发做不到的。
posted on 2025-10-19 22:44  风惊庭前叶  阅读(4)  评论(0)    收藏  举报