Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网-阿里云开发者社区

开发者社区> 橘子红了呐> 正文

Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网

简介:
+关注继续查看

学习 Neutron 系列文章:

(1)Neutron 所实现的虚拟化网络

(2)Neutron OpenvSwitch + VLAN 虚拟网络

(3)Neutron OpenvSwitch + GRE/VxLAN 虚拟网络

(4)Neutron OVS OpenFlow 流表 和 L2 Population

(5)Neutron DHCP Agent

(6)Neutron L3 Agent  

(7)Neutron LBaas

(8)Neutron Security Group

(9)Neutron FWaas 和 Nova Security Group

(10)Neutron VPNaas

(11)Neutron DVR

(12)Neutron VRRP

(13)High Availability (HA)

(14)使用 NAT 将 Linux network namespace 连接外网

(15)使用 Linux bridge 将 Linux network namespace 连接外网

 

Linux network namespace 连接外网从大类上来讲主要有两种方法:网络地址转换(NAT) 和 桥接(bridging),而桥接根据使用的网桥又可以分为使用 linux bridge 和 Open vSwitch 网络等。本文将说明 NAT 具体配置过程以及原理。

1. 环境及配置

我们可以把一个 linux network namespace 看作另一个计算机,这样看起来会更加直观:

节点 host1 的 IP 地址为 192.168.1.32. 实验使用的另一个机器 host2 的 IP 为 192.168.1.15.

为了能从在 host1 上的 netns myspace 上能 ping 通 host2 ,你需要做的配置及说明:

步骤# 命令 说明
1 ip netns add myspace 创建名称为 ‘myspace’ 的 linux network namespace
2 ip link add veth1 type veth peer name veth2 创建一个 veth 设备,一头为 veth1,另一头为 veth2
3 ip link set veth2 netns myspace 将 veth2 加入 myspace 作为其一个 network interface
4 ifconfig veth1 192.168.45.2 netmask 255.255.255.0 up 配置 veth1 的 IP 地址
5 ip netns exec myspace ifconfig veth2 192.168.45.3 netmask 255.255.255.0 up 配置 veth2 的 IP 地址,它和 veth1 需要在同一个网段上
6 ip netns exec myspace route add default gw 192.168.45.2 将 myspace 的默认路由设为 veth1 的 IP 地址
7 echo 1 > /proc/sys/net/ipv4/ip_forward    开启 linux kernel ip forwarding
8 iptables -t nat -A POSTROUTING -s 192.168.45.0/24 -o eth0 -j MASQUERADE 配置 SNAT,将从 myspace 发出的网络包的 soruce IP address 替换为 eth0 的 IP 地址
9

iptables -t filter -A FORWARD -i eth0 -o veth1 -j ACCEPT

iptables -t filter -A FORWARD -o eth0 -i veth1 -j ACCEPT

在默认 FORWARD 规则为 DROP 时显式地允许 veth1 和 eth0 之间的 forwarding

这些配置之后,host 上的 route 表中自动添加了一条路由规则:

复制代码
root@compute2:/home/s1# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.45.0    0.0.0.0         255.255.255.0   U     0      0        0 veth1
复制代码

myspace 的路由表:

root@compute2:/home/s1# ip netns exec myspace route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.45.2    0.0.0.0         UG    0      0        0 veth2
192.168.45.0    0.0.0.0         255.255.255.0   U     0      0        0 veth2

其中第一条是显式地被创建的,第二条是自动被创建的。

现在你就可以从 myspace 中 ping 外网的地址了。

2 原理

2.1 关于第八条 SNAT

如果没有设置第八条 SNAT,那么 ICMP Request 能够到达对方计算机,但是 echo reply 消息回不来,因为其目的地址为一个内部地址。

root@compute1:/home/s1# tcpdump -eni bridge1 -p icmp -v
tcpdump: listening on bridge1, link-type EN10MB (Ethernet), capture size 65535 bytes
07:40:03.827852 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 54069, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.45.3 > 192.168.1.15: ICMP echo request, id 26569, seq 1, length 64
07:40:04.829779 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 54194, offset 0, flags [DF], proto ICMP (1), length 84)

加上第八条之后,ping 能成功,也就是 ICMP echo request 能发出,echo reply 能返回。

在 host2 的网卡 eth0 上,能看到 ICMP echo request 网络包的源 IP 为 host1 的 IP:

07:44:19.360519 08:00:27:c7:cf:ca > 08:00:27:4f:56:17, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 54265, offset 0, flags [none], proto ICMP (1), length 84)
    192.168.1.15 > 192.168.1.32: ICMP echo reply, id 28534, seq 7, length 64
07:44:20.358360 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 21278, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.1.32 > 192.168.1.15: ICMP echo request, id 28534, seq 8, length 64

在 host1 的网卡 eth0 上,能看到来回网络包使用的是 host1 和 host2 的 IP 地址:

复制代码
root@compute2:/home/s1# tcpdump -envi eth0 -p icmp -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
06:31:27.285150 08:00:27:4f:56:17 > 08:00:27:c7:cf:ca, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 58781, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.1.32 > 192.168.1.15: ICMP echo request, id 29610, seq 158, length 64
06:31:27.285777 08:00:27:c7:cf:ca > 08:00:27:4f:56:17, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 23662, offset 0, flags [none], proto ICMP (1), length 84)
    192.168.1.15 > 192.168.1.32: ICMP echo reply, id 29610, seq 158, length 64
复制代码

在 host1 的 veth1 上,能看到发出的网络包的源 IP 和收到的网络包的目的 IP 皆为内部网段的 IP 地址:

复制代码
root@compute2:/home/s1# tcpdump -envi veth1 -p icmp -v
tcpdump: listening on veth1, link-type EN10MB (Ethernet), capture size 65535 bytes
06:33:13.355956 b2:52:7e:b6:e9:4e > ee:53:ae:dd:6f:7f, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 6989, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.45.3 > 192.168.1.15: ICMP echo request, id 29610, seq 264, length 64
06:33:13.356391 ee:53:ae:dd:6f:7f > b2:52:7e:b6:e9:4e, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 63, id 36067, offset 0, flags [none], proto ICMP (1), length 84)
    192.168.1.15 > 192.168.45.3: ICMP echo reply, id 29610, seq 264, length 64
复制代码

那为什么在 forwarding 发生之前,在 iptables nat 表中并没有显式做 DNAT 的情况下 veth1 和 eth0 之间有了 DNAT 呢? 

原因是 ICMP 使用了 Query ID,而 NAT 会自动根据 ICMP Query ID 对 ICMP echo reply 做 DNAT。根据 https://tools.ietf.org/html/rfc5508 的 3.1. ICMP Query Mapping 章节,当内部的 host1 发一个 ICMP Query 给外部 host2 时,linux 内核的 NAT 模块会针对 NAT 的外部地址分配一个匹配的 query ID(上面例子中的 id 29610);然后当收到 ICMP echo reply 时,NAT模块会根据 ICMP Query ID 以及 ICMP header checksum 将外部 IP 转化为内部 IP,然后再做 forwarding。也可以看出,ICMP Query ID 类似于 TCP 和 UDP 使用的端口号(port number),两者的区别在于 NAT 为 ICMP 自动做了 DNAT,而 TCP 和 UDP 则需要显式添加 DNAT 规则。

2.2 关于 IP forwarding

 (图片来源

Linux 内核在从 veth1 上收到 myspace 发过来的 ICMP 包以后,

  1. 执行 PREROTING 规则,本例不需要此配置此规则。
  2. 执行 Routing decision。它会检查网络包的目的IP地址,发现它不在本机上,说明需要进行 routing (FORWARD)。因为 Linux 上默认的 IP forwarding 是关闭的,因此需要执行第七条命令来开启它;然后再检查 iptable 规则中的这种 forwarding (ICMP 包从veth1 出再进入 eth0)。通常为了安全起见,管理员会将 FORWARD 的默认规则设置为 DROP,此时则需要执行第九条命令显式地允许(ACCEPT)所需要的 forwarding。
  3. 执行 ip forwarding。查找 host1 上的路由表,网络包会被路由到 eth0。
  4. 执行 POSTROUTING 规则。因为此时的网络包的源 IP 地址仍然为内部地址,为了避免 ICMP 网络包有去无回,需要通过 SNAT 将内部地址转换为外部地址。这就是第八条的作用。
  5. 从 eth0 发出

(3)关于 myspace 的默认路由

因为 myspace 只有一根网线(veth)连接到 veth1,因此,必须将默认的路由器地址设置为 veth1 的 IP 地址。

2.3 DNAT

  上面的配置只是为了能从 myspace 中访问外网。要使得外面网络能访问 myspace 中的应用的话,则需要在 host1 上添加 DNAT 规则,比如将 8080 端口受到的 TCP 转到内部 IP 上的 80 端口;同时还需要配置 forward 规则,允许从 eth0 出到 veth1 进。基本过程为:

对方计算机使用 host1 的 IP 地址和特定端口访问 mysapce 中的 TCP 应用 (192.168.1.32:8080),

  1. Linux 内核在从 eth0 上收到发过来的TCP包(IP 为 192.168.1.32,端口为 8080)
  2. 执行 PREROTING 规则,将目的 IP 及端口修改为 192.168.45.3 和 80
  3. 执行 Routing decision。它会检查网络包的目的IP地址,发现它不在本机上,说明需要进行 routing (FORWARD)。检查 Linux 的 IP forwarding 是否打开;然后再检查 iptable 规则中的这种 forwarding (TCP 包从 eth0 出再进入 veth1)。通常为了安全起见,管理员会将 FORWARD 的默认规则设置为 DROP,此时则需要执行类似第九条命令显式地允许(ACCEPT)所需要的 forwarding。
  4. 执行 ip forwarding。查找 host1 上的路由表,网络包会被路由到 veth1。
  5. 执行 POSTROUTING 规则。尽管有第八条规则,但是它要求源地址在内部网段,因此不会执行。
  6. 从 veth1 发出的包通过 veth 设备进入 myspace 的 veth0 网卡。
  7. 被 80 端口上的应用接收到。

 

 


    本文转自SammyLiu博客园博客,原文链接:http://www.cnblogs.com/sammyliu/p/5760125.html,如需转载请自行联系原作者


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Qt之处理QNetworkAccessManager网络连接超时
简述 在网络操作中,经常会由于各种原因引起网络连接超时,究竟何为网络连接超时? 网络连接超时:在程序默认的等待时间内没有得到服务器的响应 简述 超时原因 Qt 中的网络连接超时 如何处理超时 封装类 超时原因 引起网络连接超时的原因很多,下面,列举一些常见的原因: 网络断开,不过经常显示无法连接 网络阻塞,导致你不能在程序默认等待时间
3951 0
xshell,putty远程连接Linux并使用密钥认证
putty秘钥登录 1.软件:putty、puttygen puttygen点击Generate生成公钥和私钥   二次保障,输入设置密码   点击保存私钥文件即可。
1184 0
使用AFNetworking 3 内存泄露(转载)
原文地址:http://blog.csdn.net/d1w2hj/article/details/51793065 在使用instruments做内存泄漏分析时,发现所有使用如下语句的地方都有内存泄漏,OMG: if(!_manager){ _manager = [AFHTTPSessionManager manager]; } stack overflow上查了下并没有找到好的解决方案,去github的AFN的issue区查了下,确实有几个人提问了,但是每人给出解决方案。
663 0
理解和使用Oracle分析工具LogMiner
用LogMiner             理解和使用Oracle   8i分析工具LogMiner                 Oracle   LogMiner   是Oracle公司从产品8i以后提供的一个实际非常有用的分析工具,使用该工具可以轻松获得Oracle   重作日志文件(归档日志文件)中的具体内容,特别是,该工具可以分析出所有对于数据库操作的DML(insert、update、delete等)语句,另外还可分析得到一些必要的回滚SQL语句。
1177 0
使用Java代码连接SAP ABAP Netweaver服务器
使用Java代码连接SAP ABAP Netweaver服务器
13 0
在Entity Framework中重用现有的数据库连接字符串
本文转载:http://www.cnblogs.com/dudu/archive/2011/01/29/entity_framework_connection_string.html 如果EF在使用实体模型时候,即model first 和db first 时候,则 Entity Framework使用的连接字符串与ADO.NET是不同的,见下图: 相比于ADO.NET,Entity Framework的连接字符串不仅要存放metadata配置信息,还要存放完整的数据库连接字符串(上图中的"provider connection string"部分)。
874 0
EntityFramework 连接数据库出错
本文转载:http://www.cnblogs.com/shuang121/archive/2012/03/19/2406121.html 总结:选择“是”时,连接字符串的密码会暴露出来,“否”的时候密码而不会明文显示出来,故连字符串是错误的,运行程序的时候出现“基础提供程序在 Open 上失败。
641 0
3404
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载