iptables/netfilter
我们知道,Linux 网络协议栈非常高效,同时比较复杂。如果我们希望 在数据的处理过程中对关心的数据进行一些操作该怎么
做呢? Linux提供了一套机制来为用户实现自定义的数据包处理过程。
在Linux 网络协议栈中一组回调函数 挂节点,通过这些挂接的钩子函数可以在Linux网络栈处理数据包的过程中对数据包进行一些
操作,例如过滤,修改,丢弃等。整个挂节点技术叫做Netfilter 和 Iptables
Netfilter负责在内核中执行各种挂接的规则,运行在内核模式中;而Iptables是在用户模式下运行的进程,负责协助维护内核中Netfilter
的各种规则表。通过二者的配合来实现整个Linux 网络协议栈中灵活的数据包处理机制
Netfilter 可以在 的规则 点有 5个,分别 是 INPUT,OUTPUT , FORWARD, PREROUTING, POSTROUTING,这些 挂节点 能挂载的规则
也分 不同的类型 (也就是规则表Table) , 我们可以在不同类型的Table 中加入我们的规则。目前主要支持的Table 类型为:
RAW:
MANGLE:
NAT:
FILTER
当Linux协议栈的数据处理运行到挂节点时,它会依次调用挂接点上所有的挂钩函数,直到数据包的处理结构是明确地接收或者拒绝
处理规则
每个 规则的特性都分为以下 几 部分:
表类型 ( 准备干什么事情 ?)
什么挂接点 (什么时候起作用?)
匹配的参数是什么(针对什么样的数据包?)
匹配后有什么动作 (匹配后具体的操作是什么?)
匹配参数
匹配参数 用于 对数据包或者 TCP 数据连接的状态进行匹配。当有多个条件存在时,它们一起起作用,来达到只针对 某部分 数据进行修改的目的。
常见的匹配参数有:
流入,流出的网络接口;
来源,目的地址;
协议类型;
来源,目的端口。
匹配动作
一旦 有 数据 匹配上,就会执行相应的动作。动作类型既可以是标准的预定义 的几个动作,也可以是自定义的模块注册的动作,
或者是一个新的规则链,以便更好地组织一组动作
iptables 命令
iptables 命令用于协助用户维护各种规则。我们在使用kubernetes,Docker的过程中,通常都会去查看相关的Netfilter 配置。这里只
介绍一下如何查看规则表,详细的介绍请参照Linux的 iptables 帮助文档
查看 系统中已有 的规则的方法 如下。
iptables-save : 按照 命令的方式 打印 iptables 的内容
iptables-vnL : 以 另一种格式显示Netfilter 表的内容
-s : 匹配 源 IP 地址(即可匹配具体IP地址,也可以匹配一个网段地址)
-d : 匹配 目的IP 地址 (即可匹配具体IP地址,也可以是一个网段地址)
-m : 扩展 匹配 , 例 -m tcp -dport 22
-o 接口名: 匹配出接口
-i 接口名: 匹配入接口
动作 :
ACCEPT : 允许通过
DROP : 拒绝通过(悄悄丢弃)
REJECT : 明示 拒绝
DNAT : 目的ip 地址转换
SNAT :源 ip 地址转换
MASQUERADE : 源 ip 地址 伪装 (自动匹配出接口上的IP地址)
-i eth1 : 匹配封包进入的接口
-o eth0 :匹配封包离开的接口,结合-i,-o两个参数即可匹配封包的目的传送方向。
-p tcp: 匹配TCP协议的封包
--dport 80 : 匹配目的端口为80的封包,补充一点可搭配“!”来代表反向,如“—sport ! 80”代表匹配不是从Web发送的封包。
-j DROP 符合以上4个条件的封包丢弃
接下来,我们来分析几个例如
(1) 在刚刚启动Docker Daemon,并且 还没有启动任何 容器的时候,网络 协议栈的配置情况 如下
nat
第一条 把目标地址类型属于主机系统的本地网络地址的数据包,在数据包进入NAT表PREROUTING链时,都让它们直接jump到一个名为DOCKER的链
第二条 数据报文目标地址段不是 127.0.0.0/8,且是本地网络地址,则 执行 DOCKER 链这个动作
但是 此时 DOCKER 链为空,所有 前两条 是做了框架,并没有实际效果
-A PREROUTING -m addrtype -- dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
# 若本地发出 的 数据包不是发往 docker0 的,都需要进行动态地址修改,将源地址从容器的地址 修改维宿主机网卡的IP地址,之后就可以发送给外面的网络了
-s 172.17.0.0/16 来自 172.17.0.0/16 网段
! -o docker0 数据报文的流出接口不是 docker0
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
filter
第一条 由 docker0接收到包 就执行 DOCKER 链这个动作
-A FORWARD -o docker0 -j DOCKER
第二条是说,接收到的数据包属于以前已经建立好的连接,那么允许直接通过。这样接收到的数据包自然又走回docker0,并中转到相应的容器
由 -o docker0 docker0 出去,说明有 一个程序 像docker 发送数据包,就是 docker0属于接收方
-A FORWARD -o docker0 -m conntrack -ctstate RELATED , ESTABLISHED -j ACCEPT
第三条是,docker0发出的包,如果需要Forward到非docker0的本地IP地址的设备,则是允许的,这样,docker0设备的包就可以根据
路由规则转到宿主机的网卡设备,从而访问外面的网络
- i docker0 由docker0 进去 , 说明这个 包 由 docker0 发出,docker0是发出方
! - o 不是由docker0出去 , 说明不是发送给docker0
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
第四条,docker0的包还可以中转给docker0本身,即连接在docker0网桥上的不同容器之间的通信也是允许的
-i docker0 有docker0 进去 ,
-o docker0 由docker0出去,
docker0 发送给 docker0
-A FORWARD -i docker0 -o docker0 -j ACCEPT
容器 启动后,并将 容器的5000端口地址 映射到 宿主机的 1180端口地址,路由表的 情况
nat
可以看 到多 了几条 规则
-A POSTROUTING -s 172.17.0.19/32 -d 172.17.0.19/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
属于 172.17.0.19/32 的数据包 且 端口为0 的数据 包 ,都 动态修改
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 1180 -j DNAT --to-destination 172.17.0.19:5000
本地发出的, 且 端口 为 1180 的数据包 都 发往 172.17.0.19:5000
filter
-A DOCKER -d 172.17.0.19/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
是 宿主机 像 docker0 网桥 发出 且 发往 172.17.0.19/32 这网段,都允许通过
linux 路由
linux 系统 包含一个完整的路由功能。当IP层在处理数据发送或者转发的时候,会使用路由表来决定发往哪里。
通常情况下,如果主机与目的主机直接相连,那么主机可以直接发送IP报文到目的主机,这个过程比较简单。例如,通过
点对点的链接或通过网络共享。如果主机与目的主机没有直接相连,那么主机会将IP报文发送给默认的路由器,然后由
路由器来决定往哪发送IP报文
路由功能由IP层维护的一张路由表来实现。当主机收到数据报文时,它用此表来决策接下来应该做什么操作。当从网络
侧接收到数据报文时,IP层首先会检查报文的IP地址是否与主机自身的地址相同。如果数据报文中的IP地址是主机自身的地址,
那么报文将被发送到传输层相应的协议中去。如果报文中的IP地址不是主机自身的地址,并且主机配置了路由功能,那么
报文将被转发,否则,报文将被丢弃
我们来看看 下面 控制台输出 的 信息
[root@linux-node1 ~]# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.255.2 0.0.0.0 UG 100 0 0 eth0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
192.168.255.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
[root@linux-node1 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.255.2 0.0.0.0 UG 100 0 0 eth0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
192.168.255.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
Destination: 目标网络和目标主机。Destination 为default(0.0.0.0)时,表示这个是默认网关
Gateway: 网关地址,0.0.0.0 表示表示当前记录对应的Destination跟本机在同一个网段,通信时不需要经过网关
Genmask: Destination 字段的网络掩码,Destination 是主机时需要设置为 255.255.255.255,是默认路由时会设置为 0.0.0.0
Flags:标记
标记含义:
U 路由是活动的
H 目标是一个主机
G 需要经过网关
R 恢复动态路由产生的表项
D 由路由的后台程序动态地安装
M 由路由的后台程序修改
! 拒绝路由
Metric:路由距离,到达指定网络所需的中转数,是大型局域网和广域网设置所必需的 (不在Linux内核中使用。)
Ref:路由项引用次数 (不在Linux内核中使用。)
Use:此路由项被路由软件查找的次数
Iface:网卡名字,例如 eth0
LInux 内核路由种类
主机路由
路由表中指向单个 IP 地址或主机名的路由记录,其 Flags 字段为 H,下面示例中,对于 10.0.0.10 这个主机,通过网关 10.139.128.1网关路由
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.10 10.139.128.1 255.255.255.255 UGH 0 0 0 eth0
网络路由
主机可以到达的网络。下面示例中,对于 10.0.0.0/24 这个网络,通过网关 10.139.128.1 网关路由:
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 10.139.128.1 255.255.255.0 UG 0 0 0 eth0
默认路由
当目标主机的 IP 地址或网络不在路由表中时,数据包就被发送到默认路由(默认网关)上。默认路由的 Destination 是 default 或 0.0.0.0
Destination Gateway Genmask Flags Metric Ref Use Iface
default gateway 0.0.0.0 UG 0 0 0 eth0
route 命令
route 命令可以显示或设置 Linux 内核中的路由表,主要是静态路由。
对于局域网中的 Linux 主机,要想访问 Internet,需要将局域网的网关 IP 地址设置为这个主机的默认路由。在命令行中通过 route 命令添加的路由在网卡重启或机器重启后失效。可以在 /etc/rc.local 中添加 route 命令来保证路由设置永久有效。
选项:
-A:设置地址类型
-C:打印 Linux 内核的路由缓存
-v:显示详细信息
-n:不执行 DNS 反向查找,直接显示数字形式的 IP 地址
-e:netstat 格式显示路由表
-net:到一个网络的路由表
-host:到一个主机的路由表
参数:
add:增加路由记录
del:删除路由记录
target:目的网络或目的主机
gw:设置默认网关
mss:设置TCP的最大区块长度(MSS),单位MB
window:指定通过路由表的TCP连接的TCP窗口大小
dev:路由记录所表示的网络接口
添加路由 add
可以添加一条可用路由,或添加一条要屏蔽的路由。
添加路由
添加主机路由
添加主机路由时,需要指定网络 ID 和主机 ID,此时需要设置 netmask 255.255.255.255:
[root@VM_139_74_centos ~]# route add -net 10.0.0.10 netmask 255.255.255.255 gw 10.139.128.1 dev eth0
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.10 10.139.128.1 255.255.255.255 UGH 0 0 0 eth0
添加网络路由
添加网络路由时,只需指定网络 ID,通过 netmask 设置掩码长度:
[root@VM_139_74_centos ~]# route add -net 10.0.0.0 netmask 255.255.255.0 gw 10.139.128.1 dev eth0
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 10.139.128.1 255.255.255.0 UG 0 0 0 eth0
添加添加同一个局域网的主机
不指定 gw 选项时,添加的路由记录不使用网关:
[root@VM_139_74_centos ~]# route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
224.0.0.0 0.0.0.0 240.0.0.0 U 0 0 0 eth0
屏蔽路由
[root@VM_139_74_centos ~]# route add -net 224.0.0.0 netmask 240.0.0.0 reject
[root@VM_139_74_centos ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
224.0.0.0 - 240.0.0.0 ! 0 - 0 -
删除路由记录
跟添加路由类似,可以删除一条可用路由,或删除一条屏蔽的路由。
删除可用路由
route del -net 224.0.0.0 netmask 240.0.0.0
删除屏蔽的路由
route del -net 224.0.0.0 netmask 240.0.0.0 reject
删除和添加设置默认网关
添加或删除默认网关时,Linux 会自动检查网关的可用性:
[root@VM_139_74_centos ~]# route add default gw 192.168.1.1
SIOCADDRT: Network is unreachable
[root@VM_139_74_centos ~]# route del default gw 192.168.1.1
SIOCDELRT: No such process
部署 flannel
flannel 采用 叠加网络(Overlay Network模型来完成网络的打通
环境 :
192.168.255.128
192.168.255.129
(1) 确认 etcd 已经安装,由于 flannel 使用 etcd作为数据库,所以需要预先安装好etcd
(2) 需要在每台Node 上都安装flannel。 flannel 软件的下载地址为 https://github.com/coreos/flannel/releases, 将下载的压缩包解压
,把二进制文件 flanneld 和 mk-docker-opts.sh 复制到/usr/bin , 获取其他 PATH变量中的目录,即可完成对flannel 的安装
(3) 配置flannel
此处 以使用systemd 系统为例 对flanneld服务进行配置。 编辑服务配置文件 /usr/lib/systemd/system/flanneld.service
[root@linux-node2 sysconfig]# vim /usr/lib/systemd/system/flanneld.service
[Unit] Description=flanneld overlay address etcd agent Documentation=https://github.com/coreos/flannel After=network.service Before=docker.service
[Service] Type=notify EnvironmentFile=/etc/sysconfig/flannel ExecStart=/usr/bin/flanneld --etcd-endpoints=${FLANNEL_ETCD} $FLANNEL_OPTIONS
[Install] RequiredBy=docker.service WantedBy=multi-user.target
|
[root@linux-node2 sysconfig]# vim /etc/sysconfig/flannel
#flanneld configuration options
#etcd url location. Point this to the server where etcd runs
FLANNEL_ETCD="http://192.168.255.128:2379"
# etcd config key. this is the configuration key that flannel queries # for address range assignment FLANNEL_ETCD_KEY="/coreos.com/network"
|
(4) 在 启动 flannel 之前,需要 在etcd 中添加 一条网络记录,这个配置将用于 flannel 分配 给
每个docker 的 虚拟IP地址段
etcdctl set /coreos.com/network/config '{ "Network": "10.1.0.0/16" }'
(5)由于 flannel 将覆盖 docker0 网桥,所有如果docker 服务已经启动,则停止docker服务
(6)启动 flannel 服务
systemctl restart flannel
(7)在每个Node 节点执行以下命令 来完成对docker0网桥的设置
mk-docker-opts.sh -i
source /run/flannel/subnet.env
ifconfig docker0 ${FLANNEL_SUBNET}
(9)完成 后 使用 ifconfig 查看
flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 10.1.80.0/16 scope global flannel0
docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:89:ff:c3:04 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
(10)我们 使用 ping 命令 验证 各Node 上 docker0 之间 的相互访问
[root@linux-node1 ~]# ping 10.1.78.1
PING 10.1.78.1 (10.1.78.1) 56(84) bytes of data.
64 bytes from 10.1.78.1: icmp_seq=1 ttl=62 time=4.77 ms
64 bytes from 10.1.78.1: icmp_seq=2 ttl=62 time=1.39 ms
64 bytes from 10.1.78.1: icmp_seq=3 ttl=62 time=1.14 ms
64 bytes from 10.1.78.1: icmp_seq=4 ttl=62 time=0.958 ms
64 bytes from 10.1.78.1: icmp_seq=5 ttl=62 time=1.36 ms
64 bytes from 10.1.78.1: icmp_seq=6 ttl=62 time=1.43 ms
64 bytes from 10.1.78.1: icmp_seq=7 ttl=62 time=1.05 ms
64 bytes from 10.1.78.1: icmp_seq=8 ttl=62 time=0.949 ms
64 bytes from 10.1.78.1: icmp_seq=9 ttl=62 time=1.06 ms
出自
http://www.linuxeye.com/Linux/2065.html
https://blog.csdn.net/kikajack/article/details/80457841
《kubernetes 权威指南》