linux kernel bind()時(shí)發(fā)生了什么
配置
實(shí)驗(yàn)一下,我有兩個(gè)口lo和enp0s3, 兩個(gè)地址,如下所示。

真實(shí)物理口測試
訪問同子網(wǎng)的10.0.2.2
如果沒有地址,返回:Cannot assign requested address,說明bind失敗了。

lo口測試
訪問loopback地址127.0.0.1
如果沒有地址,返回:Cannot assign requested address,說明bind失敗了。

上圖的紅框,有個(gè)例外。
用與127.0.0.1/8同子網(wǎng)的127.0.0.2可以發(fā)包,bind成功了。
如果把本地地址改為127.0.0.1/24,則127.0.0.2可以發(fā)包,127.0.1.2不可以。
內(nèi)核代碼分析
inet_bind() 函數(shù) linux/net/ipv4/af_inet.c
命中l(wèi)ocal路由的源地址可以bind成功。

實(shí)驗(yàn)分析
通過實(shí)驗(yàn)分析如上代碼。
可以觀察到,lo口上的地址127.0.0.1會(huì)追加一條127.0.0.0/8的local路由(猜測目的是為了將loopback網(wǎng)段的包攔截在本機(jī)內(nèi)并上送)。
在試驗(yàn),增加一個(gè)1.0.0.1/8的地址在lo上,可以看見多了一個(gè)1.0.0.0/8的local路由

綜上可以解釋,為什么127.0.0.2訪問127.0.0.1可以bind成功。
透明模式
如何突破上述限制
可以使用setsockopt(IP_TRANSPARENT),
nginx的透明代理便是這樣做的,代碼如下:

詳見:
[轉(zhuǎn)]使用nginx的proxy_bind選項(xiàng)配置透明的反向代理
posted on 2025-01-09 18:14 toong 閱讀(38) 評(píng)論(0) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號(hào)