视频地址(稍后上传)
本篇文章测试如何让veth pair链接的内网网络可以被本局域网的其他宿主机访问到?
| 1、测试环境介绍 |
一台centos虚拟机
# 查看操作系统版本
cat /etc/centos-release
# 内核版本
uname -a
uname -r
# 查看网卡信息
ip a s eth0

| 2、网络拓扑 |

| 3、操作实战 |
| 3.1、操作命令 |
| 3.1.1、具体操作命令(master节点) |
ip netns add ns1
ip link add veth1a type veth peer name veth1b
ip link set veth1a netns ns1
ip netns exec ns1 ip addr add 10.244.1.2/24 dev veth1a
ip netns exec ns1 ip link set veth1a up
ip addr add 10.244.1.3/24 dev veth1b
ip link set veth1b up
ip netns exec ns1 route add default gw 10.244.1.3
iptables -t nat -A PREROUTING -d 10.211.55.122 -p tcp --dport 8090 -i eth0 -j DNAT --to 10.244.1.2:9090
echo 1 > /proc/sys/net/ipv4/ip_forward
| 3.1.2、查看一下当前环境 |
| 3.1.2.1、查看一下ns1里的路由情况 |
ip netns exec ns1 route -n

| 3.1.2.2、查看一下主网络空间里路由情况 |
route -n

| 4、具体测试 |
在ns1里,启动被测试服务http-web
| 4.1、被测试服务 |
| 4.1.1、被测试服务代码 |
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type Stu struct {
Age int
Msg string
}
const ip = "0.0.0.0"
func sayHello(w http.ResponseWriter, r *http.Request) {
stu := Stu{Age: 12, Msg: "hello world! this is DNAT+bridge+Veth pair Test!"}
stuJson, e := json.Marshal(&stu)
if e != nil {
panic(e)
}
w.Write(stuJson)
fmt.Printf("Reply MSG:%v\tlen(Msg):%d\n", string(stuJson), len(stuJson))
}
func main() {
http.HandleFunc("/", sayHello)
fmt.Printf(fmt.Sprintf("App URL: http://%s:%d\n", ip, 9090))
err := http.ListenAndServe(fmt.Sprintf("%s:%d", ip, 9090), nil)
if err != nil {
fmt.Printf("http server failed, err:%v\n", err)
return
}
}
不用关心测试代码的具体逻辑,主要是关心请求后,是否有正常打印输出即可。
| 4.1.2、本地编译,上传到Master节点 |
Makefile
build:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o http-web main.go
scp:
scp http-web root@10.211.55.122:/root
all:
make build && make scp
大家可以根据自己的实际情况进行修改。
直接执行
make all
| 4.2、在master节点上,ns1命名空间里启动http-web服务 |
ip netns exec ns1 ./http-web

| 4.3、在slave节点上,发起http-web服务请求 |
curl 10.211.55.122:8090

| 5、观察一下ns1网络空间和主网络空间里的ARP表的变化 |
ip netns exec ns1 arp -n

| 6、分析一下,整个传输过程中数据包的报文变化 |
为了观察报文变化,需要对网络设备进行抓包分析。
| 6.1、对master节点上的网络设备进行抓包 |
| 6.1.1、对ns1网络空间里的veth1a进行抓包 |
ip netns exec ns1 tcpdump -nn -i veth1a
ip netns exec ns1 tcpdump -nn -i veth1a -w icmp-veth1a.pcap

| 6.1.2、对主网络空间里的veth1b进行抓包 |
tcpdump -nn -i veth1b
tcpdump -nn -i veth1b -w icmp-veth1b.pcap
veth1b可以参考veth1a。
| 6.1.3、对主网络空间里的eth0进行抓包 |
tcpdump -nn -i eth0 -p tcp and port 8090
tcpdump -nn -i eth0 -p tcp and port 8090 -w icmp-eth0.pcap

| 6.2、对slave节点上的网络设备进行抓包 |
| 6.2.1、对主网络空间里的eth0进行抓包 |
tcpdump -nn -i eth0 -p tcp and port 8090
tcpdump -nn -i eth0 -p tcp and port 8090 -w icmp-eth0.pcap
可以参考122节点上的eth0数据抓取情况。
| 6.3、重新发起请求 |
为了恢复到最初始的状态,最好重启master、slave两台服务器。
重新根据操作命令,重新创建一下网络拓扑。
在slave节点,重新发起请求
curl 10.211.55.122:8090

| 6.4、请求过程,数据包的报文变化情况 |

上面是Slave节点,下面是Master节点
主要是观察一下,经过DNAT后,哪些发生了变化。
| 7、分析一下,整个传输过程中经过了哪些iptables规则链 |
为了验证测试,分别在master节点、slave上添加日志埋点;
此过程,需要使用到rsyslog服务
| 7.1、在master节点上安装rsyslog服务 |
yum -y install rsyslog
| 7.1.1、更新配置文件 |
echo "kern.* /var/log/iptables.log" >> /etc/rsyslog.conf

.*,表示所有等级的消息都添加到iptables.log文件里
信息等级的指定方式
- .XXX,表示 大于XXX级别的信息
- .=XXX,表示等于XXX级别的信息
- 如,kern.=notice /var/log/iptables.log, 将notice以上的信息添加到iptables.log里
- .!XXX, 表示在XXX之外的等级信息
| 7.1.2、重启rsyslog服务 |
systemctl restart rsyslog
systemctl status rsyslog

| 7.2、在slave节点上安装rsyslog服务 |
可完全参考master节点安装过程
| 7.3、添加针对icmp协议的DNAT规则 |
如果测试的是tcp服务的协议的话,添加日志埋点时,可能存在测试不足的情况。
因为tcp协议,除了我们自己测试在用外,其他服务也可能在用tcp服务等等吧。
因此,这里使用icmp协议来测试。
(因为测试环境只有我们在用icmp协议,可以唯一确定,然后将规则链的匹配条件设置到最大)
下面是针对icmp协议,添加的DNAT规则
(也就是说,主要有请求目的IP是10.211.55.122,请求协议是ICMP的,就将目的IP进行重定向)
iptables -t nat -A PREROUTING -p icmp -i eth0 -j DNAT --to 10.244.1.2

| 7.4、添加日志埋点 |
| 7.4.1、在master节点上,添加日志埋点 |
将当前的日志统计清零
iptables -t nat -Z
iptables -t filter -Z
插入日志埋点前,先查看一下,当前的现状
iptables -t nat -nvL PREROUTING --line-number
iptables -t filter -nvL FORWARD --line-number
iptables -t nat -nvL POSTROUTING --line-number
插入日志埋点
iptables -t nat -I PREROUTING -p icmp -j LOG --log-prefix "Nat-PREROUTING-1-"
iptables -t filter -A FORWARD -p icmp -j LOG --log-prefix "Filter-FORWARD-1-"
iptables -t nat -I POSTROUTING -p icmp -j LOG --log-prefix "Nat-POSTROUTING-1-"

实时查看日志
tail -f /var/log/iptables.log
| 7.4.2、在slave节点上,添加日志埋点 |
将当前的日志统计清零
iptables -t nat -Z
iptables -t filter -Z
插入日志埋点前,先查看一下,当前的现状
iptables -t nat -nvL OUTPUT --line-number
iptables -t filter -nvL OUTPUT --line-number
iptables -t nat -nvL POSTROUTING --line-number
iptables -t nat -nvL INPUT --line-number
iptables -t filter -nvL INPUT --line-number
插入日志埋点
# 匹配出去的数据包
iptables -t nat -I OUTPUT -p icmp -j LOG --log-prefix "Nat-OUTPUT-1-"
iptables -t filter -A OUTPUT -p icmp -j LOG --log-prefix "Filter-OUTPUT-1-"
iptables -t nat -I POSTROUTING -p icmp -j LOG --log-prefix "Nat-POSTROUTING-1-"
# 匹配进来的数据包
iptables -t nat -I PREROUTING -p icmp -j LOG --log-prefix "Nat-PREROUTING-1-"
iptables -t nat -I INPUT -p icmp -j LOG --log-prefix "Nat-INPUT-1-"
iptables -t filter -I INPUT -p icmp -j LOG --log-prefix "Filter-INPUT-1-"
实时查看日志
tail -f /var/log/iptables.log
| 7.5、发起请求测试 |
在slave节点,重新发起请求
ping 10.211.55.122

| 7.6、重新观察日志情况 |
| 7.6.1、观察slave节点上iptables日志变化 |
先观察主动发起请求的一侧
tail -f /var/log/iptables.log

| 7.6.2、观察master节点上iptables日志变化 |
再观察被请求方
tail -f /var/log/iptables.log

| 7.7、第1次请求、反馈都经历了哪些iptable链 |
| 7.7.1、请求过程,经历的iptables链 |

| 7.7.2、反馈过程,经历的iptables链 |

| 7.8、从第2次开始,请求、反馈都经历了哪些iptable链(仅供参考) |

从第2次请求开始,只会走OUTPUT,input,forward链了。
| 8、总结 |
- 本篇文章模拟了如何将veth pair链接的内部网络的服务暴露出来。
- 通过dnat技术,端口映射方式,将内部网络的tcp服务,udp服务,http服务暴露出来。
- 分析了整个过程数据包的报文内容变化情况
- 分析了整个过程中都经历了哪些规则链。
- 第1次请求过程
- 第2次,3次,。。。。请求过程的区别
- 实际应用中,其实,就是如何将容器里的服务暴露出来。原理是一样的。
| 点击 下面 返回 专栏目录 |
<<零入门kubernetes网络实战>>技术专栏之文章目录


















