利用 NAT VPS 进行流量中转

Contents
  1. 1. 准备
  2. 2. 使用 firewalld 进行中转
  3. 3. 使用 UFW 进行中转
  4. 4. 使用 iptables 进行中转
    1. 4.1. CentOS 下保存规则
    2. 4.2. Debian & Ubuntu 下 保存规则:
  5. 5. 使用 socat 进行中转
  6. 6. 目标机的设置
  7. 7. 一些大陆 NAT VPS 商
  8. 8. References

本文最后更新于 2020 年 5 月 13 日


本文以 CentOS 8 和 Debian 10 & Ubuntu 18.04 为例,介绍如何在 NAT VPS 上设置流量中转。

开始前,请先根据实际使用的操作系统,参照以下文章对服务器进行各种必要的配置:

本文以 sammy 用户为例,进行中转机的设置,并默认已按初始化配置文章对服务器进行了配置。

本文将介绍四种方法:firewalldUFWiptables,和 socat(推荐)来进行流量中转,根据需要选取其中一种方法操作即可。亦可根据需要,将目标机设置为只允许中转机访问。

其中,firewalldUFWiptables 均可对 TCP 和 UDP 进行转发,而 socat 还可以对包含域名的地址进行转发。


准备

  • 购买合适的 NAT VPS,此处提供一些服务商
  • 了解 NAT VPS 的基本使用方法,例如搞清楚 NAT VPS 一般需要在服务商处查看端口映射的设置
  • 基础 Linux 操作知识,并了解 vim 编辑器的基本使用方法

使用 firewalld 进行中转

此方法在 CentOS 下较为简便(CentOS 8 默认使用 firewalld),因此也推荐使用此方法。

检查 firewalld 运行状态,输出应为 running

1
firewall-cmd --state

接下来设置端口转发:

1
2
3
4
5
6
sudo firewall-cmd --zone=public --permanent --add-port 本机端口号/tcp
sudo firewall-cmd --zone=public --permanent --add-port 本机端口号/udp
sudo firewall-cmd --zone=public --permanent --add-forward-port=port=本机端口号:proto=tcp:toport=目标端口号:toaddr=目标地址
sudo firewall-cmd --zone=public --permanent --add-forward-port=port=本机端口号:proto=udp:toport=目标端口号:toaddr=目标地址
sudo firewall-cmd --zone=public --permanent --add-masquerade
sudo firewall-cmd --reload

其中 目标地址 为目标服务器的 IP 地址。

至此,利用 firewalld 设置中转的方法介绍完毕。另可根据使用场景,对目标机的防火墙进行配置,令其只接受来自此 NAT VPS 的流量。


使用 UFW 进行中转

此方法在 Debian & Ubuntu 下较为简便(Ubuntu 18.04 默认使用 UFW)。

首先要修改 /etc/sysctl.conf 文件:

1
2
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

修改 /etc/default/ufw

1
sudo vim /etc/default/ufw
/etc/default/ufw
1
DEFAULT_FORWARD_POLICY="ACCEPT"

修改 /etc/ufw/before.rules

1
sudo vim /etc/ufw/before.rules

*filter 之前添加:

/etc/ufw/before.rules
1
2
3
4
5
6
7
8
9
10
11
12
13
# nat table rules
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# port forwarding
-A PREROUTING -p tcp --dport 本机端口号 -j DNAT --to-destination 目标地址:目标端口号
-A PREROUTING -p udp --dport 本机端口号 -j DNAT --to-destination 目标地址:目标端口号
-A POSTROUTING -p tcp -d 目标地址 --dport 目标端口号 -j SNAT --to-source 本机内网地址
-A POSTROUTING -p udp -d 目标地址 --dport 目标端口号 -j SNAT --to-source 本机内网地址

# commit to apply changes
COMMIT

其中,目标地址 为目标服务器的 IP 地址,本机内网地址 为本机在内部局域网的 IP 地址。

重启 UFW:

1
sudo ufw disable && sudo ufw enable

至此,利用 UFW 设置中转的方法介绍完毕。


使用 iptables 进行中转

对于其他系统或不使用 firewalld 的用户,也可以使用 iptables 进行中转设置。

首先要修改 /etc/sysctl.conf 文件:

1
2
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

如下显示的是不同端口(本机端口号和目标机端口号不同)的中转方法:

1
2
3
4
sudo iptables -t nat -A PREROUTING -p tcp --dport 本机端口号 -j DNAT --to-destination 目标地址:目标端口号
sudo iptables -t nat -A PREROUTING -p udp --dport 本机端口号 -j DNAT --to-destination 目标地址:目标端口号
sudo iptables -t nat -A POSTROUTING -p tcp -d 目标地址 --dport 目标端口号 -j SNAT --to-source 本机内网地址
sudo iptables -t nat -A POSTROUTING -p udp -d 目标地址 --dport 目标端口号 -j SNAT --to-source 本机内网地址

其中,目标地址 为目标服务器的 IP 地址,本机内网地址 为本机在内部局域网的 IP 地址。

CentOS 下保存规则

1
sudo service iptables save

Debian & Ubuntu 下 保存规则:

1
2
3
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
sudo netfilter-persistent start

至此,利用 iptables 设置中转的方法介绍完毕。


使用 socat 进行中转

如所需转发的端口数量较少,则个人推荐使用此方法。

首先安装 socat,此处以 Debian & Ubuntu 系统为例:

1
sudo apt install socat

配置进行 TCP 转发,编辑服务文件,可根据需要自行调整此文件名,本文以 socat-tcp 为文件名作例:

1
sudo vim /etc/systemd/system/socat-tcp.service

添加以下内容,注意替换其中的 本机端口号目标地址目标端口号,其中,目标地址 可以是 IP 地址,也可以是域名地址:

/etc/systemd/system/socat-tcp.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Socat TCP Forwarding Service
After=network.target

[Service]
Type=simple
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
DynamicUser=true
ExecStart=/usr/bin/socat TCP4-LISTEN:本机端口号,reuseaddr,fork TCP4:目标地址:目标端口号
Restart=always

[Install]
WantedBy=multi-user.target

接着,启动 socat 的 TCP 转发服务:

1
2
sudo systemctl enable socat-tcp
sudo systemctl start socat-tcp

如果还需要进行 UDP 转发,则继续编辑一个新文件,可根据需要自行调整此文件名,本文以 socat-udp 为文件名作例:

1
sudo vim /etc/systemd/system/socat-udp.service

添加以下内容,注意替换其中的 本机端口号目标地址目标端口号,其中,目标地址 可以是 IP 地址,也可以是域名地址:

/etc/systemd/system/socat-udp.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=Socat UDP Forwarding Service
After=network.target

[Service]
Type=simple
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
DynamicUser=true
ExecStart=/usr/bin/socat -T 60 UDP4-LISTEN:本机端口号,reuseaddr,fork UDP4:目标地址:目标端口号
Restart=always

[Install]
WantedBy=multi-user.target

接着,启动 socat 的 UDP 转发服务:

1
2
sudo systemctl enable socat-udp
sudo systemctl start socat-udp

本机防火墙放行此端口:

1
sudo ufw allow 本机端口号

至此,利用 socat 设置中转的方法介绍完毕。另可根据使用场景,对目标机的防火墙进行配置,令其只接受来自此 NAT VPS 的流量。


附注:使用 nohup 直接启动 socat 转发 TCP 的方法

1
2
nohup /usr/bin/socat -d TCP4-LISTEN:本机端口号,reuseaddr,fork,su=nobody TCP4:目标地址:目标端口号 >> /var/log/socat.log 2>&1 &
nohup /usr/bin/socat -d -T 60 UDP4-LISTEN:本机端口号,reuseaddr,fork,su=nobody UDP4:目标地址:目标端口号 >> /var/log/socat.log 2>&1 &

上面两条命令可在 root 用户下执行。


目标机的设置

此处示例的目标机为 Debian & Ubuntu 系统,安装并启用了 UFW:

如需同时允许 TCP 和 UDP 入站:

1
sudo ufw allow from 中转机地址 to any port 端口号

如需只允许 TCP 入站:

1
sudo ufw allow proto tcp from 中转机地址 to any port 端口号

如需只允许 UDP 入站:

1
sudo ufw allow proto udp from 中转机地址 to any port 端口号

以上命令中,中转机地址 为 NAT VPS 的公网 IP 地址。

其他系统、其他防火墙控制软件的操作与之类似,放行来自 NAT VPS 的 IP 的指定端口号即可。


一些大陆 NAT VPS 商

注:本小节包含的链接含有 aff 值。

  • CloudIPLC:热门稳定,价格合理,需要及时关注补货情况
  • 碳云:价格较低,年付套餐手慢则无
  • AkkoCloud:二次元风格的网站,产品同样抢手

References

How to open and close ports on RHEL 8 / CentOS 8 Linux

Port Forwarding

NAT 主机的正确食用方法

通过 iptables 实现 IP 端口数据包转发服务配置

关于 NAT VPS 的使用说明

NAT VPS 的正确食用方式

NAT VPS 主机端口转发(流量中转)教程

国内中转高性价比方案:NAT VPS + iptables 端口流量转发

通过国内服务器转发流量

Ubuntu UFW 防火墙设置

Setup a Shadowsocks relay

在 Azure 搭建 ShadowSocks 国内跳板,并开启 UDP 转发

UFW Essentials: Common Firewall Rules and Commands

How To Setup a Firewall with UFW on an Ubuntu and Debian Cloud Server

Configure Uncomplicated Firewall (UFW) on Ubuntu

配置 iptables、ufw 端口转发

iptables port forwarding only for a certain range of IP

gartnera / tcp-forward.service

socat 中转单个端口,支持 TCP 和 UDP

socat(1) - Linux man page

socat 多端口转发配置

socat 使用手册

How to run socat in the background?

socat examples

Migrate socat init script to systemd

Can socat be started directly by systemd?

socat port forwarding for https

Socat:可能是最好的转发伴侣

Why is “fork” needed by socat when connecting to a web server?

socat UDP IPv6 to IPv4 gateway results in lots of processes

systemd.exec

CAPABILITIES(7)