linux参数arp_filter,arp_ignoe,arp_announce,rp_filter详解
rp_filter
rp_filter全称reverse path filter用于控制系统是否开启对数据包源地址的校验。这是一个网卡级别的参数也就是说每张网卡可以设置不同的值。此参数有三个值0、1、2具体含义
0不开启源地址校验。
1开启严格的反向路径校验。对每个进来的数据包校验其反向路径是否是最佳路径接收报文的网卡和回数据的网卡是否是同一张网卡。如果反向路径不是最佳路径则直接丢弃该数据包。
2开启松散的反向路径校验。对每个进来的数据包校验其源地址是否可达即反向路径是否能通通过任意网卡如果反向路径不通则直接丢弃该数据包。
Current recommended practice in RFC3704 is to enable strict mode to prevent IP spoofing from DDos attacks. If using asymmetric routing or other complicated routing, then loose mode is recommended.
The max value from conf/{all,interface}/rp_filter is used when doing source validation on the {interface}.
Default value is 0. Note that some distributions enable it in startup scripts.
一般来说出去的报文都会经过默认路由出去查看默认路由的方法
客户端与服务端建立连接时如果服务端因为这个参数校验不过而导致报文丢弃那么在服务端抓包的现象是能收到客户端的报文但是服务端没有进行任何回应。
rp_filter导致的丢包数量可以通过netstat命令查看
netstat -s | grep IPReversePathFilter
可以设置打印syslog:
sysctl -w net.ipv4.conf.all.log_martians=1
设置之后可以在/var/log/messages中看到对应的日志
IPv4: martian source 10.185.203.166 from 10.185.203.172, on dev eth1
ll header: 00000000: fa 16 3e dd 7b bb fa 16 3e 28 00 60 08 00
以上日志表示
10.185.203.166 目的ip
10.185.203.172 源ip
eth1 接收到报文的网卡
ll header: link layer header
fa 16 3e dd 7b bb 目的mac
fa 16 3e 28 00 60 源mac
08 00 上层协议号08 00: IP Packets 86 dd: IPv6 Packet 08 06: ARP Packet
需要注意的是除了rp_filter会导致出现火星包之外还有其他情况也会导致出现火星包。比如源地址全0等等。。。。
参考
arp_filter
arp_filter和rp_filter类似都是进行反向路径检验不过是专门针对arp协议的。而且行为也有所不同。
arp_filter将对arp报文的源ip进行判断决定响应行为官方文档描述如下
arp_filter - BOOLEAN
0 - (default) The kernel can respond to arp requests with addresses from other interfaces. This may seem wrong but it usually makes sense, because it increases the chance of successful communication. IP addresses are owned by the complete host on Linux, not by particular interfaces. Only for more complex setups like load- balancing, does this behaviour cause problems.
1 - Allows you to have multiple network interfaces on the same subnet, and have the ARPs for each interface be answered based on whether or not the kernel would route a packet from the ARP'd IP out that interface (therefore you must use source based routing for this to work). In other words it allows control of which cards (usually 1) will respond to an arp request.
arp_filter for the interface will be enabled if at least one of conf/{all,interface}/arp_filter is set to TRUE, it will be disabled otherwise
当arp_filter设置为0时如果从某张网卡上收到了一个arp请求同时目的ip在此主机上不论目的ip是否在接收到此arp请求的网卡上那么主机便会进行响应响应的mac地址为接收到此请求的网卡的mac地址。
当arp_filter设置为1时如果从某张网卡上收到了一个arp请求同时目的ip在此主机上不要求目的ip是一定在接收到此arp请求的网卡上那么主机便会查询到此请求的源ip的路由是通过哪张网卡如果是接收到此arp请求的网卡则发送arp响应响应的mac地址为接收到此请求的网卡的mac地址。
在如下组网图中
如果182.11.1.107想要和10.10.1.1通信那A就必须将arp_filter设置为0否则182.11.1.107无法通过arp协议获取到10.10.1.1的mac地址也就无法和10.10.1.1进行通信。
但是某些场景arp_filter设置为0又会导致问题。
考虑以下场景 例子借鉴于此文章
http://3ms.huawei.com/hi/group/6891/wiki_4306543.html
主机A的两张网卡处于同一个局域网中这种情况B发送的arp请求A的两张网卡都能收到。如果A的arp_filter参数设置为0那么两张网卡将分别进行回复。这将导致B处得到的ip地址与mac的对应关系混乱。解决此问题的办法是将A的arp_filter参数设置为1。
通过下面的例子来深入理解A的arp_filter参数设置为1的情况下此种场景下具体的行为
三张网卡二层互通103和104在同一个主机上。从107上向103和104发送ping请求。
1. arp_filter设置为0的场景
fep0:/etc/sysconfig/network # echo 0 >/proc/sys/net/ipv4/conf/eth3/arp_ignore
fep0:/etc/sysconfig/network # echo 0 >/proc/sys/net/ipv4/conf/eth4/arp_ignore
fep0:/etc/sysconfig/network # echo 0 >/proc/sys/net/ipv4/conf/all/arp_filter
1 在107上发送ping 103的请求
2 在eth3和eth4上分别抓包
可以发现两张网卡都进行了回复。这个时候就出现了ip对mac对应关系混乱的情况。解决方法是将arp_filter设置为1。
2. arp_filter设置为1的场景
echo 1 >/proc/sys/net/ipv4/conf/all/arp_filter
(只要有一项设置为true即可)
1 在107上发送ping 103的请求
因为到107的路由是经过eth3所以只有eth3进行了回复并且回复的mac是eth3的mac。
2 在107上发送ping 104的请求
可以发现还是eth3进行的回复回复的mac是eth3的mac。eth4同样没有进行回复。
这样就解决了同一个主机上有多张同网段的网卡的通信问题。但是103和104都对应同一个mac。
arp_ignore
定义对目标地址为本机IP的ARP查询不同的应答模式
参数说明
整型值的范围为0-8常用的只有012默认为0。
0(默认值回应任何网络接口上对任何本地IP地址的arp查询请求比如eth0=192.168.0.1/24, eth1=10.1.1.1/24,那么即使eth0收到来自10.1.1. 2这样地址发起的对10.1.1.1的arp查询也会回应一而原本这个请求该是出现在eth1上也该由eth1回应的响应的mac自然是eth0的mac。
1 只回答目标IP地址是来访网络接口本地地址的ARP查询请求比如eth0=192.168.0.1/24, eth1=10.1.1.1/24,那么当eth0收到对192.168.0.1的查询请求时会进行回复(不论arp请求源地址是啥)而对待查询的ip为10.1.1.1的arp查询不会进行回复
2 只回答目标IP地址是来访网络接口本地地址并且请求源IP必须在该网络接口的子网段内的ARP查询请求。比如eth0=192.168.0.1/24, eth1=10.1.1.1/24, eth0收到对192.168.0.1的查询请求源地址为 10.1.1.2(不同网段)不会进行不会回答而会回答192.168.0.2发起的对192.168.0.1的arp查询请求
那么当arp_ignore设置为1时eth3和eth4就只会分别回复对103和104的arp请求不仅解决了同一个主机上有多张同网段的网卡的通信问题。而且103和104和mac的对应关系也是正确的。
当某张网卡收到一个arp报文会先进行arp_filter检验如果检验失败直接丢弃报文。如果校验成功则会进行arp_ignore检验。可以理解为arp_filter是一个比较粗糙的检验而arp_ignore是一个比较细致的检验。为什么要设置两级校验呢arp_filter与rp_filter又是什么关系呢
arp_ignore用来设置对arp查询请求的应答模式还有一个参数arp_announce用来设置主动发送arp请求时对源地址的选择模式。
arp_announce
arp_announce的作用是控制系统在对外发送arp请求时如何选择arp请求数据包的源IP地址。比如系统准备通过网卡发送一个数据包a这时数据包a的源IP和目的IP一般都是知道的然后根据目的IP查询路由表确定发送数据包的网卡。链路层要转发数据需要获取下一跳的MAC地址通过发送arp请求得到。arp请求的目的IP是下一跳IP而arp请求的源IP是什么呢 可能第一反应会以为肯定是数据包a的源IP地址但是这个也不是一定的arp请求的源IP是可以选择的控制这个地址如何选择就是arp_announce的作用
arp_announce参数常用的取值有012。
0允许使用任意网卡上的IP地址作为arp请求的源IP通常就是使用数据包的源IP。
1Try to avoid local addresses that are not in the target’s subnet for this interface. This mode is useful when target hosts reachable via this interface require the source IP address in ARP requests to be part of their logical network configured on the receiving interface. When we generate the request we will check all our subnets that include the target IP and will preserve the source address if it is from such subnet. If there is no such subnet we select source address according to the rules for level 2
个人理解
在发送该数据包的网卡上如果找到和数据包的源地址在同一个网段的地址则使用数据包的源地址作为arp请求的源地址。否则使用配置为2时的规则。
2忽略IP数据包的源IP地址在发送此请求的网卡上查找与arp请求的目标地址一般和数据包的目标地址并不相同在同一网段的ip地址作为arp请求的源地址。如果找不到则随便取某张网卡的第一个ip地址。
sysctl.conf中包含all和eth/lo具体网卡的arp_announce参数其中较大的值生效。
由此也可以理解为什么LVS在DR模式下要配置
echo"2" >/proc/sys/net/ipv4/conf/all/arp_announce
因为如果使用数据包的源ip浮动ip发送arp请求则会更新其他主机的arp缓存导致报文不能被正常转发至LVS从而导致LVS不能正常工作。设置为2则arp请求会使用发送arp请求的网卡上合适的地址而浮动ip配置在环回地址上所以一定不会以浮动ip作为arp请求的源地址。
base_reachable_time
arp表项mac缓存表老化时间
参数的配置方法
以上4个参数都分别有all,default,lo,eth1,eth2...等表示对应不同的网卡。当all和具体网卡的参数值不一致时取较大值生效。
一般只需修改all和某个具体网卡的参数即可取决于你需要修改哪个网卡。
参数的值可以通过
sysctl -a | grep net.ipv4.conf.xxx
命令进行查看
修改有三种方法以修改lo网卡为例
1. 修改/etc/sysctl.conf文件然后sysctl -p刷新到内存。此配置在机器重启之后依然有效
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_announce=2
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.lo.rp_filter=1
net.ipv4.conf.all.arp_filter=1
net.ipv4.conf.lo.arp_filter=1
2. 使用sysctl -w直接写入内存在机器重启之后无效
sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.lo.arp_ignore=1
3. 修改/proc文件系统在机器重启之后无效
echo "1">/proc/sys/net/ipv4/conf/all/arp_ignore
echo "1">/proc/sys/net/ipv4/conf/lo/arp_ignore
参考
Linux内核参数之arp_ignore和arp_announce
https://www.cnblogs.com/lipengxiang2009/p/7451050.html
- 点赞
- 收藏
- 关注作者
评论(0)