学习 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. 基于STM32Cube的DAC数模转化

    1. STM32Cube配置 1.1 DAC配置   1.2 TIM6 配置 1.3 利用Cube产生工程程序,MDK打开软件       在主循环上添加语句:      HAL_TIM_Base_S ...

  2. Autofac - 事件

    Autofac在提供之前那些方法的时候, 同时提供了五个事件, 这一篇就看一下这几个事件. 一.五大事件 builder.RegisterType<Person>().As<IPer ...

  3. csharp: ODP.NET,System.Data.OracleClient(.net 4.0) and System.Data.OleDb读取Oracle g 11.2.0的区别

    ODP.NET: 引用: using Oracle.DataAccess; //Oracle g 11.2.0 using Oracle.DataAccess.Client; using Oracle ...

  4. nginx 添加nginx-http-concat模块

    github地址:https://github.com/alibaba/nginx-http-concat/tree/master 简单的描述一下吧,网上说的安装新的模块需要重新编译nginx,具体的 ...

  5. IDCM项目学习笔记

    项目介绍: IDCM:Internet Data center monitoring 网络数据中心监控平台 IRP:Information Resource planing 信息资源规划 1.设置表中 ...

  6. Java的关键字与标识符

    Java作为一门编程语言,与其他语言一样,有字符集.标识符.和关键字.变量.常量.语句等编程语言的基本要素. 1.关键字 abstract boolean break byte case catch ...

  7. Javaweb学习笔记——EL表达式

    一.前言 EL表达式是什么? 简而言之,可以这样理解,EL表达式全名为:Exprexxsion Language,原先是JSTL 1.0为了方便存取数据而定义的语言,到了JSTL 2.0便正式成为标准 ...

  8. 新建 ASP.NET Core MVC 项目 -- Hello World!

    一.创建一个空项目 请查看 新建 .NET Core 项目 -- Hello World! 一节,新建一个项目: 二.添加引用并修改配置为 MVC 修改 .vscode\launch.json 文件 ...

  9. 学习Javascript闭包(Closure)

    闭包作用 1.让变量驻留在内存中 2.函数外部可以读取函数内部的私有变量 <!DOCTYPE html> <html lang="en"> <head ...

  10. 微信小程序开发总结

    一.设计 无需开发者开发的 1.小程序加载动画: 2.页面下拉刷新加载样式: 3.微信控件(拥有完整的操作反馈):如弹出框.通知.模态框...   建议用微信自己的 1.加载.反馈样式(全局.局部) ...