linux kernel bind()时发生了什么

配置

实验一下,我有两个口lo和enp0s3, 两个地址,如下所示。

 

真实物理口测试

访问同子网的10.0.2.2

如果没有地址,返回:Cannot assign requested address,说明bind失败了。

 

lo口测试

访问loopback地址127.0.0.1

如果没有地址,返回:Cannot assign requested address,说明bind失败了。

 

上图的红框,有个例外。

用与127.0.0.1/8同子网的127.0.0.2可以发包,bind成功了。

如果把本地地址改为127.0.0.1/24,则127.0.0.2可以发包,127.0.1.2不可以。

 

内核代码分析

inet_bind() 函数  linux/net/ipv4/af_inet.c

命中local路由的源地址可以bind成功。

 实验分析

通过实验分析如上代码。

可以观察到,lo口上的地址127.0.0.1会追加一条127.0.0.0/8的local路由(猜测目的是为了将loopback网段的包拦截在本机内并上送)。

在试验,增加一个1.0.0.1/8的地址在lo上,可以看见多了一个1.0.0.0/8的local路由

 

 

综上可以解释,为什么127.0.0.2访问127.0.0.1可以bind成功。

 

透明模式

如何突破上述限制

可以使用setsockopt(IP_TRANSPARENT),

nginx的透明代理便是这样做的,代码如下:

 

详见:

[转]使用nginx的proxy_bind选项配置透明的反向代理

 
 

 

posted on 2025-01-09 18:14  toong  阅读(6)  评论(0编辑  收藏  举报