- 論壇徽章:
- 0
|
反向路徑過濾——reverse path filter
不知道自己理解的對(duì)不對(duì),請(qǐng)大家斧正。
一、原理
先介紹個(gè)非對(duì)稱路由的概念
參考《Understanding Linux Network Internals》三十章,
30.2. Essential Elements of Routing
Symmetric routes and asymmetric routes
Usually, the route taken from Host A to Host B is the same as the route used to get back from Host B to Host A; the route is then called symmetric . In complex setups, the route back may be different; in this case, it is asymmetric.
關(guān)于反向路徑過濾,參考《Understanding Linux Network Internals》三十一章,
31.7. Reverse Path Filtering
We saw what an asymmetric route is in the section "Essential Elements of Routing in Chapter 30. Asymmetric routes are not common, but may be necessary in certain cases. The default behavior of Linux is to consider asymmetric routing suspicious and therefore to drop any packet whose source IP address is not reachable through the device the packet was received from, according to the routing table.
However, this behavior can be tuned via /proc on a per-device basis, as we will see in Chapter 36. See also the section "Input Routing" in Chapter 35.
二、檢查流程
如果一臺(tái)主機(jī)(或路由器)從接口A收到一個(gè)包,其源地址和目的地址分別是10.3.0.2和10.2.0.2,
即<saddr=10.3.0.2, daddr=10.2.0.2, iif=A>, 如果啟用反向路徑過濾功能,它就會(huì)以<saddr=10.2.0.2, daddr=10.3.0.2>為關(guān)鍵字去查找路由表,如果得到的輸出接口不為A,則認(rèn)為反向路徑過濾檢查失敗,它就會(huì)丟棄該包。
關(guān)于反向路徑過濾,ipv4中有個(gè)參數(shù),這個(gè)參數(shù)的說明在Documentation/networking/ip-sysctl.txt中。
rp_filter - INTEGER
0 - No source validation.
1 - Strict mode as defined in RFC3704 Strict Reverse Path
Each incoming packet is tested against the FIB and if the interface
is not the best reverse path the packet check will fail.
By default failed packets are discarded.
2 - Loose mode as defined in RFC3704 Loose Reverse Path
Each incoming packet's source address is also tested against the FIB
and if the source address is not reachable via any interface
the packet check will fail.
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.
三、源代碼分析
git commit 373da0a2a33018d560afcb2c77f8842985d79594
net/ipv4/fib_frontend.c
192 int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos,
193 int oif, struct net_device *dev, __be32 *spec_dst,
194 u32 *itag)
195 {
// 是否啟用反向路徑過濾
216 /* Ignore rp_filter for packets protected by IPsec. */
217 rpf = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(in_dev);
// 檢查路由表
// 注意這里的源地址賀目的地址是反過來的,
// 看看其他函數(shù)是如何調(diào)用fib_validate_source()就明白了。
227 if (fib_lookup(net, &fl4, &res))
228 goto last_resort;
// 運(yùn)行到這里,說明反向路由是可達(dá)的
// 下面分成兩種情況檢查輸出設(shè)備是否就是輸入設(shè)備
237 #ifdef CONFIG_IP_ROUTE_MULTIPATH
// 啟用多路徑時(shí),任意一個(gè)匹配,就用它了
238 for (ret = 0; ret < res.fi->fib_nhs; ret++) {
239 struct fib_nh *nh = &res.fi->fib_nh[ret];
240
241 if (nh->nh_dev == dev) {
242 dev_match = true;
243 break;
244 }
245 }
246 #else
247 if (FIB_RES_DEV(res) == dev)
248 dev_match = true;
249 #endif
250 if (dev_match) {
// 反向路徑過濾檢查成功了,返回
251 ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
252 return ret;
253 }
254 if (no_addr)
255 goto last_resort;
// 運(yùn)行到這里,說明反向路徑檢查是失敗的,
// 如果rpf為1,表示反向路徑檢查必須成功才能正常返回,
// 否則只好返回錯(cuò)誤。
256 if (rpf == 1)
257 goto e_rpf;
278 e_rpf:
279 return -EXDEV;
四、實(shí)例
本網(wǎng)絡(luò)有三臺(tái)機(jī)器,R1, R2 和PC,子網(wǎng)掩碼都是255.255.0.0。
R2 (10.1.0.2) ---- (10.1.0.1) R1 (10.3.0.1) ---- (10.3.0.2) PC
R2 (10.2.0.2) ---- (10.2.0.1) R1
注意,設(shè)置R2的默認(rèn)路由為10.1.0.1
現(xiàn)在,從PC上能夠ping通10.1.0.2,但是ping不通10.2.0.2。
tcpdump顯示,R2接到icmp request,但是不發(fā)送icmp reply。
PC
$ ip a
inet 10.3.0.2/16 brd 10.3.255.255 scope global eth0
$ ip r
10.3.0.0/16 dev eth0 proto kernel scope link src 10.3.0.2
default via 10.3.0.1 dev eth0
R1
$ ip a
inet 10.1.0.1/16 brd 10.1.255.255 scope global eth1
inet 10.2.0.1/16 brd 10.2.255.255 scope global eth2
inet 10.3.0.1/16 brd 10.3.255.255 scope global eth3
$ ip r
10.1.0.0/16 dev eth1 proto kernel scope link src 10.1.0.1
10.2.0.0/16 dev eth2 proto kernel scope link src 10.2.0.1
10.3.0.0/16 dev eth3 proto kernel scope link src 10.3.0.1
R2
$ ip a
inet 10.1.0.2/16 brd 10.1.255.255 scope global eth1
inet 10.2.0.2/16 brd 10.2.255.255 scope global eth2
$ ip r
10.1.0.0/16 dev eth1 proto kernel scope link src 10.1.0.2
10.2.0.0/16 dev eth2 proto kernel scope link src 10.2.0.2
default via 10.1.0.1 dev eth1
請(qǐng)問這是什么原因?
你可以返回去細(xì)細(xì)思考5分鐘......
我的回答:
假設(shè)R2的兩個(gè)接口分別為A(10.1.0.2)、B(10.2.0.2)。
從PC ping 10.2.0.2時(shí),包的路徑是PC-->10.3.0.1-->10.2.0.2,
此時(shí)包的 <saddr=10.3.0.2, daddr=10.2.0.2, iif=B>,
以<saddr=10.2.0.2, daddr=10.3.0.2>進(jìn)行反向路徑檢查, 得到輸出設(shè)備是A,
因?yàn)槟康牡刂肥?0.3.0.2,只能使用默認(rèn)路由。A!=B,反向路徑檢查失敗,
丟棄該包!
五、如何解決
兩種方法:
1 On R2:
ip route add 10.3.0.0/16 via 10.2.0.2
增加一條關(guān)于10.3.0.0/16子網(wǎng)的路由。
2 On R2:
/etc/sysctl.conf
net.ipv4.conf.default.rp_filter = 0
禁用反向路徑檢查。
|
|