Linux策略路由及iptables mangle、ip rule、ip route关系及一种Network is unreachable错误
iptables、ip rule、ip route关系,一个包到达网络协议层,首先会被iptables的managle表打上标记(当然也可以不打),然后给ip rule匹配,找到对应的路由表,最后根据ip route table的路由表找到对应出口接口。
如果ip rule规则不对,则很可能出现ping网关(这种情况下ping同子网,跟路由没关系)的时候直接报错:
# ping 192.168.1.1
connect: Network is unreachable
而指定接口再ping 的时候就能通:
# ping -I wlan0 192.168.1.1
PING 10.193.20.64 (10.193.20.64) from 10.193.20.83 eth5: 56(84) bytes of data.
64 bytes from 10.193.20.64: icmp_seq=1 ttl=64 time=0.345 ms
64 bytes from 10.193.20.64: icmp_seq=2 ttl=64 time=0.354 ms
看看iptable内容(iptables各过滤表的优先级为managle -> nat -> filter):
使用Netfilter的managle机制针对特定的数据包设置MARK值(长度为32bit),下面例子将HTTP(端口80)数据包的MARK值设置为1,SMTP及POP3数据包(端口25和110)的MARK值设置为2,其余数据包则设置MARK值为3。
iptables -t mangle -A FORWARD -i eth3 -p tcp –dport 80 -j MARK –set-mark 1
iptables -t mangle -A FORWARD -i eth3 -p tcp –dport 25 -j MARK –set-mark 2
iptables -t mangle -A FORWARD -i eth3 -p tcp –dport 110 -j MARK –set-mark 2
iptables -t mangle -A FORWARD -i eth3 -j MARK –set-mark 3
下面的表是个实际中的表,上面的配置没有体现。
# iptables -t mangle –list
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
PREROUTING_direct all — anywhere anywhere
PREROUTING_ZONES_SOURCE all — anywhere anywhere
PREROUTING_ZONES all — anywhere anywhere
Chain INPUT (policy ACCEPT)
target prot opt source destination
INPUT_direct all — anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
FORWARD_direct all — anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
OUTPUT_direct all — anywhere anywhere
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
POSTROUTING_direct all — anywhere anywhere
Chain FORWARD_direct (1 references)
target prot opt source destination
Chain INPUT_direct (1 references)
target prot opt source destination
Chain OUTPUT_direct (1 references)
target prot opt source destination
Chain POSTROUTING_direct (1 references)
target prot opt source destination
Chain PREROUTING_ZONES (1 references)
target prot opt source destination
PRE_public all — anywhere anywhere [goto]
Chain PREROUTING_ZONES_SOURCE (1 references)
target prot opt source destination
Chain PREROUTING_direct (1 references)
target prot opt source destination
Chain PRE_public (1 references)
target prot opt source destination
PRE_public_log all — anywhere anywhere
PRE_public_deny all — anywhere anywhere
PRE_public_allow all — anywhere anywhere
Chain PRE_public_allow (1 references)
target prot opt source destination
MARK tcp — anywhere anywhere tcp dpt:biimenu MARK set 0x64 打标记为0x64
MARK tcp — anywhere anywhere tcp dpt:http MARK set 0x65 打标记为0x65
Chain PRE_public_deny (1 references)
target prot opt source destination
Chain PRE_public_log (1 references)
target prot opt source destination
# iptables -t filter –list
略
再看ip route内容:
Linux 最多可以支持 255 张路由表,在默认情况下,系统有三个路由表,这三个路由表的功能如下:
local路由表(id为255):路由表local包含本机路由及广播信息。例如,在本机上执行ssh 127.0.0.1时,就会参考这份路由表的内容,在正常情况下,只要配置好网卡的网络设置,就会自动生成local路由表的内容,我们应该也不必修改其内容。
main路由表(id为254):使用传统命令route -n所看到的路由表就是main的内容。Linux系统在默认情况下使用这份路由表的内容来传输数据包,因此,其内容极为重要,在正常情况下,只要配置好网卡的网络设置,就会自动生成main路由表的内容。
default路由表(id为253):最后是default路由表,这个路由表在默认情况下内容为空;除非有特别的要求,否则保持其内容为空即可。
另外有个id为 0 的unspec表保留无作用。
如果有需要,则可以自行再添加其他路由表。
# cat /etc/iproute2/rt_tables
255 local
254 main
253 default
0 unspec
#
# ip route show table main
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.150
#
# ip route show table default
#
# ip route show table local
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 192.168.1.0 dev wlan0 proto kernel scope link src 192.168.1.150
local 192.168.1.150 dev wlan0 proto kernel scope host src 192.168.1.150
broadcast 192.168.1.255 dev wlan0 proto kernel scope link src 192.168.1.150
#
# ip route show table wlan0
default via 192.168.1.1 dev wlan0 proto static
192.168.1.0/24 dev wlan0 proto static scope link
再看ip rule内容(前面数字为优先级,值越小的越优先匹配):
# ip rule list
0: from all lookup local 这个表示是优先匹配local路由表,对应ip route show table local的local路由表。
10000: from all fwmark 0xc0000/0xd0000 lookup legacy_system 这里表示iptables的mark标记为0xc0000(0xd0000为掩码,进来的包先和xd0000做AND与计算,结果为0xc0000的包)的查找legacy_system路由表。
10500: from all iif lo oif wlan0 uidrange 0-0 lookup wlan0 这里表示从lo环回接口输入、从wlan0接口输出、uid为0(即系统用户)的包查找wlan0路由表。
13000: from all fwmark 0x10063/0x1ffff iif lo lookup local_network
13000: from all fwmark 0x10065/0x1ffff iif lo lookup wlan0
14000: from all iif lo oif wlan0 lookup wlan0
15000: from all fwmark 0x0/0x10000 lookup legacy_system
16000: from all fwmark 0x0/0x10000 lookup legacy_network
17000: from all fwmark 0x0/0x10000 lookup local_network
19000: from all fwmark 0x65/0x1ffff iif lo lookup wlan0 这里表示iptables的mark标记为0x65(0x1ffff为掩码,进来的包先和0x1ffff做AND与计算,结果为0x65的包)、输入接口为lo环回地址的包查找wlan0路由表,对应上面的ip route show table wlan0的wlan0路由表。
22000: from all fwmark 0x0/0xffff iif lo lookup wlan0 这里表示iptables的mark标记为0x0(0xffff为掩码,进来的包先和0xffff做AND与计算,结果为0x0的包)、输入接口为lo环回地址的包查找wlan0路由表,对应上面的ip route show table wlan0的wlan0路由表。
32000: from all unreachable
上面这个ip rule list里面没有default和main是不对的,一般都会有的。
每行各部分的解释(具体查看ip rule命令help):
xx: 第一列数字是优先级,小的数字优先级高
中间部分内容:如 from all, 这是规则。
fwmark 0x10064: 其中0x64(十进制为100)就是该网络的netid
lookup [xxx] : 表示搜索xxx路由表,1-252之间的数字或名称
整行的意思就是,如果一个数据包符合规则(源地址、目的地址、协议、端口、数据包大小、内容等),则使用指定路由表。
比如要添加几条:
# ip rule add from all lookup main prio 23000
# ip rule add from all lookup default prio 32000
CentOS 7.x下让ip route路由和ip rule永久生效,重启不丢失:
假定要给eth1(假定接口地址为 192.168.100.140)增加rule和路由表:
# vi /etc/iproute2/rt_tables
255 local
254 main
253 default
0 unspec
128 mynet
# vi /etc/sysconfig/network-scripts/rule-eth1
from 192.168.100.0/24 lookup mynet
from 192.168.101.0/24 lookup mynet 假定192.168.101.0/24这个网段的包也走路由表mynet,则需要加这一条。
# vi /etc/sysconfig/network-scripts/route-eth1
192.168.100.0/24 dev eth1 table mynet 这个相当于是scope link类型的路由,和接口地址在同一网段。
default via 192.168.100.1 dev eth1 table mynet
10500: from all iif lo oif wlan0 uidrange 0-0 lookup wlan0 这里表示从lo环回接口输入、从wlan0接口输出、uid为0(即系统用户)的包查找wlan0路由表
从lo环回接口输入、从wlan0接口输出,这一块我不太明白,答主可以详细讲一下这个吗?