ubuntu 下配置SNAT和DNAT

2016/12/25 posted in  linux
  • release

SNAT和DNAT的区别

先讲一下Snat和Dnat 的区别,网上讲这的比较多,这里可以先摘抄一段帮助理解:

SNAT,DNAT,MASQUERADE都是NAT
MASQUERADE是SNAT的一个特例
SNAT是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样,接收方就认为数据包的来源是被替换的那个IP的主机
MASQUERADE是用发送数据的网卡上的IP来替换源IP,因此,对于那些IP不固定的场合,比如拨号网络或者通过dhcp分配IP的情况下,就得用MASQUERADE
DNAT,就是指数据包从网卡发送出去的时候,修改数据包中的目的IP,表现为如果你想访问A,可是因为网关做了DNAT,把所有访问A的数据包的目的IP全部修改为B,那么,你实际上访问的是B

下面看到这个是感觉比较靠谱,也比较能够理解的回答:

SNAT,这个规则被用于将Outbound Packets的 Source IP Address 翻译为能够被目标网路识别到的地址。例如:想要让Private Network VMs上到Internet,那么,就可以配置SNAT Rules,然后SNAT Rules就会将Private IP Address翻译为Public IP Address,进而实现被Public Network接受;
DNAT,这个规则被用于将Inbound Packets的Destination IP Address翻译为能够被内部Private Network VMs识别。例如:如果想要将一个 Private IP Address VM(Web Server)发布到 Internet,希望外部的用户能够访问到这个Private IP Address VM,则可以配置 DNAT Rules 实现这个诉求;

总结一下:
SNAT 主要管Outbound, 也就是网络数据包流出,简单的也可以说成内网访问公网。
DNAT主要管Inbound,也就是网络数据包流入,简单的也可以说成公网访问内容。

其中SNAT主要起到,对于内网的服务器,没有公网ip,但是需要访问公网,这时可以采用SNAT,将内网机器与网关配置,从而可以访问公网。这也是当前电信运营商采用的方法,1个ip可以对应6万户上网。从截包也可以看到,一般都是使用的40000左右的端口出去。

DNAT 主要起到公网来访问内网的主机。如果发生情况是公网的某台机器,希望访问某个内网的端口,此时内网电脑是没有公网ip 的,那么我们可以在公网主机上配置DNAT,比如开启40000端口,然后映射到内网ip的某个端口,比如我们希望在公网访问内网的电脑的ssh,我们就可以开通22端口。 在外网访问公网ip的4000端口就能映射到内网主机的22端口。

SNAT的配置

给内网网卡配置静态IP(此前确保另一张外网网卡eth0已经能够正常访问Internet。已经为eth1配置过内网静态IP的可以跳过本步)

sudo ip addr add 10.0.0.11/24 dev eth1

  
这里假设eth1的IP为10.0.0.11,。

配置NAT规则

sudo iptables -A FORWARD -o eth0 -i eth1 -s 10.0.0.0/24 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -F POSTROUTING
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

  
第一条规则允许转发初始网络包,第二条规则允许转发已经建立连接后的网络包,第三条则设置NAT。

接下来需要保存iptables规则,确保每次重启时能够加载NAT规则:

[root@localhost ~]# iptables -A FORWARD -o eth1 -i eth0 -s 192.168.12.0/24 -m conntrack --ctstate NEW -j ACCEPT
[root@localhost ~]# iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
[root@localhost ~]# iptables -t nat -F POSTROUTING
[root@localhost ~]# iptables -t nat -A POSTROUTING -o eht1 -j MASQUERADE

保存iptables规则

sudo iptables-save | sudo tee /etc/iptables.sav

编辑/etc/rc.local文件,将下面的一行添加到“exit 0”之前:

iptables-restore < /etc/iptables.sav

  
这样以后每次重启机器时都会自动加载NAT相关的iptables规则。  

启用路由转发,编辑/etc/sysctl.conf 文件,删除起始的“#”,解除

#net.ipv4.ip_forward=1

 
的注释。然后使其生效:

sudo sysctl -p

  
这样我们就完成了网关一端的设置。

Client端

一旦网关机器设置完成,任何OS的客户端都能够通过连接到网关而访问外部网络。这里以Ubuntu Server作为client为例,假设client的eth0连接到网关eth1所在的内网10.0.0.0上,

为eth0指派静态IP(需与server端的eth1在同一网段,如果已经配置过则可以跳过本步),编辑/etc/network/interfaces文件:

auto eth0
iface eth0 inet static
        address 10.0.0.31
        netmask 255.255.255.0
        gateway 10.0.0.11
        dns-nameservers YourDNSServer

  因为我们的网关服务端并没有充当DNS服务器,此处需要额外指定client的DNS服务器,通常从网络服务提供商(ISP)那里获得。

接下来配置路由网关

sudo route add default gw 10.0.0.11 dev eth0

  
使网关配置生效,如果以前已经生成过_etc_resolv.conf文件中的nameserver字段,那么这时client应该已经能够访问外部网络了,否则需要编辑_etc_resolv.conf,添加字段:

nameserver YourDNSServer

  
由于在_etc_network/interfaces文件中已经配置过dns-nameservers,所以重新启动client机器时不会影响DNS配置。

此时client已经能够通过网关机器访问外网,如果不知道ISP的DNS服务器地址,可以使用OpenDNS作为替代。

DNAT 的配置

在DNAT中,要把规则定义在PREROUTING链中

iptables -t nat -A PREROUTING -d 10.0.0.1 -j DNAT –-to-destination 172.16.93.1

此条规则将请求IP为10.0.0.1的数据包转发到后端172.16.93.1主机上

iptables -t nat -A PREROUTING -d 10.0.0.1 -p tcp –-dport 80 -j DNAT –-to-destination 172.16.93.1

此条规则将请求IP为10.0.0.1并且端口为80的数据包转发到后端的172.16.93.1主机上,通过定义不同的端口,就可以实现PNAT,将同一个IP不同的端口请求转发到后端不同的主机

iptables -t nat -A PREROUTING -d 10.0.0.1 -p tcp –-dport 80 -j DNAT –-to-destination 172.16.93.1:8080

此条规则在上条规则的基础上,发往后端的数据包的目标端口改为8080,在后端主机的web服务器上使用8080端口接收访问, 这样能更好的保护后端主机

这样就可以实现内网的机器进行外放访问,并可以让外放访问内网服务器了。

说明一下,这种方式和nginx的proxy功能,可以起到两个不同的作用。

SNAT 的另一种配置方式

用上面讲述的snat 的配置方式,可能出现SNAT只能绑定在一张网卡上,如果我们要针对多个内网网段或者多个内网网卡进行snat的时候,使用上面的方法会命令重复,从而我发配置相应的snat。我们需要使用如下的方法配置

iptables  -F
iptables  -P   INPUT   ACCEPT
iptables  -P   FORWARD ACCEPT
iptables  -t nat  -A  POSTROUTING   -s  192.168.1.0/24   -o  eth0 -j MASQUERADE

其中第一步为清除原始的所有iptables规则,第二三步为打开INPUT和FORWARD。
第四步为配置nat。

使用这种方式可以同时配置多个网段和多个端口的SNAT。

#配置10网段的SNAT
iptables -t nat -A POSTROUTING -s 10.11.11.0/24 -o eth2 -j MASQUERADE
#配置192.168网段的snat
iptables -t nat -A POSTROUTING -s 192.168.11.0/24 -o eth2 -j MASQUERADE
#配置DNAT
iptables -t nat -A PREROUTING -d 61.183.247.113 -p tcp --dport 40001 -j DNAT --to-destination 192.168.11.88:22

查看SNAT和DNAT配置

默认的使用iptables -L 主要查看的是filter表的内容,没有办法看到nat表的内容,如果要查看我们已经配置的snat和dnat的内容,可以使用如下命令

root@ubuntu:~# iptables -t nat -vnL POSTROUTING --line-number
Chain POSTROUTING (policy ACCEPT 1 packets, 64 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1    77640 5908K MASQUERADE  all  --  *      eth2    0.0.0.0/0            0.0.0.0/0           
2        0     0            all  --  *      eth2    10.11.11.0/24        0.0.0.0/0           
3        0     0            all  --  *      eth2    192.168.11.0/24      0.0.0.0/0           
root@ubuntu:~# iptables -t nat -vnL PREROUTING --line-number
Chain PREROUTING (policy ACCEPT 2445 packets, 201K bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        1    64 DNAT       tcp  --  *      *       0.0.0.0/0            61.183.247.113       tcp dpt:40000 to:10.11.11.154:22
2        1    64 DNAT       tcp  --  *      *       0.0.0.0/0            61.183.247.113       tcp dpt:40001 to:192.168.11.88:22

整理

使用iptables配置SNAT和DNAT实际上就是使用 iptabeles的nat转换,也就是操作iptables 的nat表。

所以对iptables的操作都是使用 iptables -t nat 开头。而我们使用的SNAT和DNAT实际上对应了两张表的内容,SNAT对应POSTROUTING,DNAT对应PREROUTING。

而iptables的其他命令都适用。比如说查询我们可以使用 iptables -t nat -L PREROUTINGiptables -t nat -L POSTROUTING, 如果希望查询的内容更多,可以采用 iptables -t nat -vnL PREROUTING --line-number

默认的iptables -L实际上是查询的filter表 的内容。

同样的,删除我们可以采用查询到line-number之后,采用iptables -t nat -D REEROUTING 3来进行删除。