学习 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 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 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 veth2
192.168.45.0 0.0.0.0 255.255.255.0 U 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 bytes
::03.827852 :::4f:: > :::c7:cf:ca, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [DF], proto ICMP (), length )
192.168.45.3 > 192.168.1.15: ICMP echo request, id , seq , length
::04.829779 :::4f:: > :::c7:cf:ca, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [DF], proto ICMP (), length )

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

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

::19.360519 :::c7:cf:ca > :::4f::, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [none], proto ICMP (), length )
192.168.1.15 > 192.168.1.32: ICMP echo reply, id , seq , length
::20.358360 :::4f:: > :::c7:cf:ca, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [DF], proto ICMP (), length )
192.168.1.32 > 192.168.1.15: ICMP echo request, id , seq , length

在 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 bytes
::27.285150 :::4f:: > :::c7:cf:ca, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [DF], proto ICMP (), length )
192.168.1.32 > 192.168.1.15: ICMP echo request, id , seq , length
::27.285777 :::c7:cf:ca > :::4f::, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [none], proto ICMP (), length )
192.168.1.15 > 192.168.1.32: ICMP echo reply, id , seq , length

在 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 bytes
::13.355956 b2::7e:b6:e9:4e > ee::ae:dd:6f:7f, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [DF], proto ICMP (), length )
192.168.45.3 > 192.168.1.15: ICMP echo request, id , seq , length
::13.356391 ee::ae:dd:6f:7f > b2::7e:b6:e9:4e, ethertype IPv4 (0x0800), length : (tos 0x0, ttl , id , offset , flags [none], proto ICMP (), length )
192.168.1.15 > 192.168.45.3: ICMP echo reply, id , seq , length

那为什么在 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 端口上的应用接收到。

Netruon 理解(11):使用 NAT 将 Linux network namespace 连接外网的更多相关文章

  1. Netruon 理解(12):使用 Linux bridge 将 Linux network namespace 连接外网

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  2. 【转】理解Docker容器网络之Linux Network Namespace

    原文:理解Docker容器网络之Linux Network Namespace 由于2016年年中调换工作的原因,对容器网络的研究中断过一段时间.随着当前项目对Kubernetes应用的深入,我感觉之 ...

  3. centos中NAT模式下静态IP连接外网

    使用linux虚拟机时,通常会用到yum命令来安装软件,然而这个命令需要连外网下载软件,用maven下载jar包也需要外网.虚拟机在内网可以互相ping通,然而ping不了外网,于是通过试验,终于找到 ...

  4. vmware 中Linux系统怎么连接外网?

    VMware虚拟机有三种网络模式,分别是Bridged(桥接模式).NAT(网络地址转换模式).Host-only(主机模式). VMware workstation安装好之后会多出两个网络连接,分别 ...

  5. linux: centos设置ip以及连接外网

    注明:我使用的的使centos 7,所有文件名是ifcfg-enp0s3, 一. 设置虚拟机中linux的ip,使本地能连通虚拟机的linux系统 1>.进入本地windows的cmd,输入ip ...

  6. 虚拟机NAT模式连接外网

    虚拟机三种联网方式: 一.NAT(推荐使用)                功能:①可以和外部网络连通    ②可以隔离外部网络 二.桥接模式                        功能:直接 ...

  7. NAT模式下VMware中CentOS7无法连接外网的解决方法

    故障现象 ----------------------------------------------------------------------------------------------- ...

  8. 虚拟机中的centos在nat模式下连不上外网

    这两天需要配置ftp服务器,可是虚拟机在nat模式下死活连不上外网,主机能够通过该ssh与虚拟机进行连接,虚拟机也能ping同一网段主机的IP地址,但就是ping不通外网, 开始我是这样配置的: 主机 ...

  9. windows,linux,cmd查看公网/外网IP

    1.linux(centos)查看公网/外网ip: curl ifconfig.me #inconfig.me是一个网站来的#或者,如果上面的无法访问curl icanhazip.com   2.Wi ...

随机推荐

  1. [WCF编程]7.实例上下文模式

    一.实例上下文模式概述 实例上下文(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在实例化服务器对象时,WCF采用了3种不同的模式:单调(Per-Call ...

  2. yii的入口文件index.php中为什么会有这两句

    yii的应用模板中,index.php中 前面会有这两句 <?php // comment out the following two lines when deployed to produc ...

  3. ffmpeg实现dxva2硬件加速

    这几天在做dxva2硬件加速,找不到什么资料,翻译了一下微软的两篇相关文档.这是第二篇,记录用ffmpeg实现dxva2. 第一篇翻译的Direct3D device manager,链接:http: ...

  4. 数据结构:链表(python版)

    #!/usr/bin/env python # -*- coding:utf-8 -*- # Author: Minion Xu class LinkedListUnderflow(ValueErro ...

  5. spring面试题(2)

    f-sp-1. Spring的aop你怎样实现? 用动态代理和cglib实现,有接口的用动态代理,无接口的用cglib f-sp-2. Spring在SSH起什么作用 整合作用 f-sp-3. Spr ...

  6. AbstractFactoryPattern(抽象工厂)

    /** * 抽象工厂模式 * 分为四部分 * 1.产品接口 * 2.产品实例 * 3.工厂接口(生产同一个产品的不同等级,这里是主要区别) * 4.工厂实例 * 工厂类最好用单例模式,但在这里主要是说 ...

  7. placeholder不兼容 IE10 以下版本的解决方法

    对于密码输入框placeholder的兼容问题:HTML代码:<input type="password" id="loginPassword" plac ...

  8. tomcat远程调试javaweb

    当把一个本地项目部署到远程服务器后有可能出现意想不到错误,这个时候通过远程调试能够更清楚的找到bug所在位置. 目前百度tomcat绝大多数方法都是在startup.sh或者catalina.sh增加 ...

  9. H5中的touch事件

    touch中共有touchstart.touchmove和touchend三个事件: touchstart:触摸开始的时候触发 touchmove:手指在屏幕上滑动的时候触发 touchend:触摸结 ...

  10. 基本排序算法——快速排序java实现

    简单的快速排序算法,我竟然花费了如此多的时间来写作,好好学习. /** * */ package basic.sort; import java.util.Arrays; import java.ut ...