内核如何决定数据包的源ip
1、Traversing of packets
Receive:
某个interface收到数据包 -> PREROUTING (manage, nat) -> routing ->
是发送给本机的数据包? -> INPUT (manage, filter) -> app
不是 -> FORWARD (manage, filter) -> POSTROUTING (manage, nat) -> 某个interface发出
Send:
app发送数据包 -> routing -> OUTPUT (manage, nat, filter) -> (re)routing -> POSTROUTING (manage, nat) -> 某个interface发出
2、routing and rerouting
对于本机 app 发出(outcoming)的流量,netfilter 有2次 routing 过程,称为 routing 和 (re)routing。在routing的过程中,内核会为数据包指定source ip
流转如下:routing —> output —> rerouting
- OUTPUT 链在 第一次 routing 之后:
对于本机 app 发出的流量,第一次 routing 除了确定下一跳之外,对于没有指定源IP的数据包,还将会为其选择源IP地址。当数据包经过了iptables OUTPUT链,某条rule为其打上了fwmark或者改变了其目标地址后,由于数据包属性已经改变,需要第二次路由,即 (re)routing。
- OUTPUT 链之后的 rerouting :
Linux内核协议栈在实现第一次路由和第二次路由时,其逻辑是一样的。但请注意由于第一次路由时会为skb选择source地址,那么第二次路由时的命中路由条目的source属性将永远不会生效,所以多个网口设备策略路由时常常需要用 MASQUERADE 重写 outcoming 数据包的 src IP 以保证正确,这是一种 workaround。
3、routing时,如何指定source ip
Send的route阶段确定了数据包的source ip和source port。source ip和source port由app发送数据包时决定。如果app没有bind某个interface并且没有设置source ip/port,则source ip时为route使用的interface ip。
具体规则:
-
1、The application is already using the socket, in which case, the source address has been chosen. Also, the application can specifically request a particular address (not necessarily a locally hosted IP) using the bind call.
-
2、The kernel performs a route lookup and finds an outbound route for the destination. If the route contains the src parameter, the kernel selects this IP address for the outbound packet. Otherwise, the kernel will choose the first address configured on the interface which falls in the same network as the destination address or the nexthop router.
翻译:
-
1、应用程序已经在使用套接字,在这种情况下,已经选择了源地址。此外,应用程序可以使用绑定调用专门请求特定地址(不一定是本地托管的 IP)。
-
2、内核执行路由查找并找到目的地的出站路由。如果路由包含 src 参数,则内核为出站数据包选择此 IP 地址。否则,内核将选择接口上配置的第一个地址,该地址与目标地址或下一跳路由器位于同一网络中。
自己bind address:
使用socket的时候可以 bind 某个 src IP:
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
注意 bind 某个 interface 并不会使"发送数据包"跳过 route decision 阶段,bind 的作用仅仅是指定发送数据包时的 src IP。
4、参考文档
- netfilter network flow
- routing-saddr-selection