视频地址(稍后上传)
本篇文章测试如何让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网络实战>>技术专栏之文章目录


















