在阿里云、腾讯云等云平台购买多台服务器时,出于成本考虑,不会为每一台服务器配置公网 IP。这样就带来一个问题,没有公网 IP 的服务器就无法访问外网。本文介绍一种使未绑定公网 IP 的服务器访问外网的可选方案,前提是购买的多台服务器中至少有一台绑定了公网 IP。
在此先介绍下基本原理和基本步骤,对网络了解得比较多的朋友可能一看就知道怎么回事了。后面再详细介绍下具体操作流程。
基本原理
使用绑定了公网 IP 的服务器作为代理进行网络的转发
基本步骤
假设有两台服务器:
- 服务器 master,绑定了公网 IP,可以访问外网
- 服务器 worker1,未绑定公网 IP,不能访问外网
操作步骤如下:
- 建立 worker1 到 master 的隧道
- 修改 worker1 的路由表,使用 master 作为路由
- 在 master 上,使用 iptables 对来源为 worker1 的请求做 SNAT 转换
详细介绍
本文以云平台购买的两个节点实例为例:
- master 节点:内网 IP 192.168.0.197
- worker 节点:内网 IP 192.168.0.196
其中 master 节点绑定了公网 IP,可以访问外网,worker 节点没有绑定公网 IP,不能访问外网。
通过 ip route show 命令查看两台主机的路由表,都有一条记录为:
default via 192.168.0.253 dev eth0
也就是说,这两台主机默认都以 192.168.0.253 作为路由转发请求,因此我们可以大概猜测网络拓扑如下:

当然真实的网络拓扑会比较复杂,这里只针对购买的两台主机做一个简化。
现在我们要做的是,worker1 节点通过 master 节点作为代理,获得访问外网的能力。
第一步:建立 master 节点到 worker1 节点的隧道
因为两台机器在一个内网中,本身是可以互通的,因此我们可以通过默认网卡在两台主机间建立隧道。

在master 节点执行如下命令
# 创建一个 IPIP 类型的虚拟网卡
# ip tun add [虚拟网卡名称] mode ipip remote [对端 IP 地址] local [本机 IP 地址]
ip tunnel add worker1_tunl mode ipip remote 192.168.0.196 local 192.168.0.197
# 启动刚刚创建的虚拟网卡
ip link set worker1_tunl up
# 为创建的虚拟网卡绑定 IP 地址
# ip add add [本机要绑定的 IP] peer [对端要绑定的 IP 地址] dev [本机要绑定 IP 的虚拟网卡名称]
ip add add 192.168.3.100 peer 192.168.3.101 dev worker1_tunl
这样执行 ip addr show 命令可以看到多了如下一个网卡:

可以看到该网卡绑定了 IP:192.168.3.100
同样的,在 worker1 节点执行如下命令
ip tunnel add master_tunl mode ipip remote 192.168.0.197 local 192.168.0.196
ip link set master_tunl up
ip add add 192.168.3.101 peer 192.168.3.100 dev master_tunl
执行 ip addr show 命令看到 worker1 节点多了如下网卡:

可以看到该网卡绑定了 IP:192.168.3.101
现在我们验证下隧道是否建立成功,在 master 节点执行 ping 192.168.3.101

同样在 worker1 节点执行 ping 192.168.3.100

可以看到,两台主机已经可以通过设置的 IP 互相访问了,这样两台主机之间的隧道就建立成功了
第二步:在 worker1 节点修改路由表,让 master 节点作为 worker1 节点默认路由的网关
我们可以先执行 ip route show 查看下当前的默认路由

该路由显示 worker1 节点上的默认路由使用 192.168.0.253 作为默认网关
首先,执行 ip route del default 删除默认网关
然后,执行 ip route add default via 192.168.3.100 dev master_tunl 设置使用 master 节点作为默认网关, 注意这里使用创建的 master_tunl 虚拟网卡作为网络设备
第三步:在 master 节点通过 iptables 工具,对通过我们创建的隧道过来的请求进行 SNAT 转换
因为从 worker1 过来的请求源地址为 192.168.3.101,是一个内网地址,如果不进行 nat 转换的话,外网中的请求是无法到达 worker1 节点的
我们执行如下命令进行 nat 设置
# 我们设置的隧道网段为 192.168.3.0/24, 如下设置会把源地址在网段 192.168.3.0/24 的请求进源地址转换,
# 源地址会被伪装成出口网卡的 IP 地址
iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -o eth0 -j MASQUERADE
以上就是所有的步骤了,我们来验证下
在 worker1 节点执行 ping baidu.com

可以看到 worker1 节点可以访问外网了
问题
- 按上述步骤设置后仍然无法访问外网?
检查 master 节点是否开启了路由转发功能,该方案需要转发节点开启转发功能
开启方式:
- 需要修改 sysctl.conf 文件,配置 net.ipv4.ip_forward = 1
- 执行 sysctl -p 使之生效
关键词:局域网服务器访问外网方案(局域网外网如何访问)