前两天在工作中遇到一个需求,某192.168.1.0/24内网网段内只有一台主机A连接到了公网,A的两块网卡分别有一个公网地址(123.234.345.456)和一个内网地址(192.168.1.10),现需要内网的另一台主机B(192.168.1.77)连接到互联网下载某些东西,同时将B的某服务端口开放到公网上,两台主机的系统均为CentOS7。

主要参考了 和  两篇文章,事实证明并不需要改路由表等操作,简单几条命令即可完成我们的需求。

解决思路为使用iptables的转发功能,当然CentOS7自带了firewalld防火墙也有转发功能,但因为配置内网转接公网也需要通过iptables进行,这里就都使用iptables(CentOS7无需安装和启用iptables.service,我们只是用到了iptables命令)。

首先查看B主机的网卡

[root@~]# ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 20:04:0f:f5:25:c0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.77/24 brd 192.168.1.255 scope global noprefixroute em1
       valid_lft forever preferred_lft forever
    inet6 fe80::2204:fff:fef5:25c0/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

编辑网卡ens1的配置文件

[root@r740 redis]# vi /etc/sysconfig/network-scripts/ifcfg-ens1

TYPE=Ethernet
PROXY_METHOD=none
BOOTPROTO=static   #也可以设置为dhcp,具体看路由器是否开启了dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
NAME=ens1
UUID=531a7963-406d-4e4d-b949-efe5d55d6cc
DEVICE=ens1
ONBOOT=yes
IPADDR=192.168.1.77
PREFIX=24
GATEWAY=192.168.1.10 #重点在这里,网关要设成主机A的内网地址
DNS1=114.114.114.114
~                                                                                                                                                              
~                                                                                                                                                              
~

:wq保存修改,然后重启网络服务

systemctl restart network

systemctl restart NetworkManager  #如果安装了图形界面,network会被NetworkManager代替

之后回到A主机,开启A的内核转发

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf && sysctl -p
iptables -t nat -A POSTROUTING -s 192.168.1.77 -j MASQUERADE    #进行ip伪装,对来源为192.168.1.77的主机数据报进行转发,如果改为192.168.1.0/24,则对整个内网网段的主机都进行转发

OK,现在在主机B ping一个公网网址,发现已经可以ping通了。

 


将以下代码保存成shell脚本,执行,即可开启对应端口的公网映射

#!/bin/bash
pro='tcp'

src_host='123.234.345.456' #主机A的公网地址
src_port=16379  #在主机A上要映射的端口

Dst_Host='192.168.1.77'  #主机B的内网地址
Dst_Port=6379  #在主机B上要映射过去的端口

# 清空规则(如果自己以前定义过规则,比如上文的转发规则,则慎用!)
#iptables -F
#iptables -X
#iptables -Z
#iptables -t nat -F

# Destination network  address translate (dnat)

iptables -t nat -A PREROUTING  -p $pro -d $src_host  --dport $src_port -j DNAT --to $Dst_Host:$Dst_Port

iptables -A FORWARD -p $pro -d $Dst_Host --dport $Dst_Port -j ACCEPT

# 本地连接不经过prerouting,只经过output链,所以想要在服务器A通过本地ip访问服务器B需要在output 链增加dnat规则

iptables -t nat -A OUTPUT -p $pro -d $src_host --dport $src_port -j DNAT --to $Dst_Host:$Dst_Port

在主机B运行redis服务后,扫描123.234.345.456的13679端口,发现已经是开启状态,端口转发成功。

如果希望持久化配置

iptables-save > /etc/sysconfig/iptables

将新加规则写入到配置文件中。