4000-520-616
欢迎来到免疫在线!(蚂蚁淘生物旗下平台)  请登录 |  免费注册 |  询价篮
主营:原厂直采,平行进口,授权代理(蚂蚁淘为您服务)
咨询热线电话
4000-520-616
当前位置: 首页 > 新闻动态 >
新闻详情
内核的DNAT与ARP_redwingz的博客-CSDN博客
来自 : CSDN技术社区 发布时间:2021-03-24

 

Linux内核在实现多对一或者多对多的DNAT时 可指定多个目的IP地址 这就造成一个问题 如果其中有的地址并没有配置在接口上 那么这些地址对于外部设备而言 ARP就是不可达 无法进行通信。

 ------------ | Internal | | Server 1 | |------------| ---------- ----------- | 10.10.0.2/24 | External | eth0 | Linux | 10.10.0.1 | | Device |--------------| Gateway |-------------- ---------- ----------- eth1 | 20.20.20.20 20.20.20.1 | 10.10.0.3/24 ------------ | Internal | | Server 2 | ------------ 

如上图拓扑所示 LINUX网关的左侧网卡连接外部网络 此处是IP地址为20.20.20.2的设备 网关的右侧网卡连接在内部的10.10.0.0/24的内部网络中。假如在内网中服务器10.10.0.2对外提供服务 可使用如下iptables命令配置DNAT将访问流量映射进来

iptables -t nat -A PREROUTING -d 20.20.20.1 -j DNAT --to-destination 10.10.0.1  


这样iptables将在PREROUTING hook点检查所有目的地址为20.20.20.1的流量 然后全部映射到内部10.10.0.1的服务器上。如果我们另有一个公网IP 20.20.20.2 需要将其映射到内部的第二台服务器上 IP地址为10.10.0.3 与以上iptables命令类似 使用如下命令进行映射

iptables -t nat -A PREROUTING -d 20.20.20.2 -j DNAT --to-destination 10.10.0.2 

另外 需要将公网IP地址20.20.20.2配置在Linux网关的eth0接口上 否则 外部设备 20.20.20.20 将不知道20.20.20.2地址的存在 即ARP请求其IP地址 将得不到回应。如果有多个公网IP需要映射 都需要配置在外部网卡eth0上 IP地址可以是不同网段。

$ sudo ip addr add 20.20.20.2/24 dev eth0 
$ sudo ip addr add 20.20.20.3/24 dev eth0 

查看配置的IP地址

$ ip addr show3: eth0: BROADCAST,MULTICAST mtu 1500 qdisc noop state UP group default qlen 1000 link/ether 00:0c:29:74:7f:0e brd ff:ff:ff:ff:ff:ff inet 20.20.20.1/24 scope global eth0 valid_lft forever preferred_lft forever inet 20.20.20.2/24 scope global secondary eth0 valid_lft forever preferred_lft forever inet 20.20.20.3/24 scope global secondary eth0 valid_lft forever preferred_lft forever
内核对ARP处理

Linux内核中arp_process函数处理接收到的ARP报文。在判断是一个ARP请求报文之后 查询路由表 确认ARP请求的目标地址tip为本机地址后 才有可能需要回复ARP请求。路由查询结果rt_type需要为RTN_LOCAL类型。

static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb){ if (arp- ar_op htons(ARPOP_REQUEST) ip_route_input_noref(skb, tip, sip, 0, dev) 0) { rt skb_rtable(skb); addr_type rt- rt_type; if (addr_type RTN_LOCAL) { dont_send arp_ignore(in_dev, sip, tip); if (!dont_send IN_DEV_ARPFILTER(in_dev)) dont_send arp_filter(sip, tip, dev); if (!dont_send) { n neigh_event_ns( arp_tbl, sha, sip, dev); if (n) { arp_send_dst(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, dev- dev_addr, sha, reply_dst);}

另外一个判断条件 是在arp_ignore的子函数confirm_addr_indev中 需要确认目标IP地址是否配置在出接口上。毫无疑问 以上两个条件都成立 对于外部IP地址的ARP请求都会得到相应。


ARP的修改

清楚了以上的ARP处理过程 可以避免在外部网卡eth0上配置多个IP地址 直接修改内核代码 对ARP相应。只需要两个地方的改动。第一在arp_process中查询路由之后 ip_route_input_noref函数 如果目的IP不是指向本地地址 再次查询内核的DNAT规则中配置的目的IP 如果匹配到 即认为这是本地地址 第二在arp_ignore中在接口IP列表中找不目标IP后 也需要在此查询DNAT规则中的目的IP 如果有认为条件成立 回复ARP响应。二层地址使用入口设备的MAC地址。

 

SNAT

对于SNAT 问题是一样的 如果配置了多个映射的源IP 需要在外出接口上配置这些IP地址 以响应对端的ARP地址请求。

sudo iptables -t nat -A POSTROUTING -s 20.20.2.0/24 -j SNAT -o ens38 --to-source 9.9.9.1-9.9.9.20


内核版本

Linux-4.15

 

\"\" \"\" \"\" 点赞 \"\" \"\" 评论

本文链接: http://arpzgmbh.immuno-online.com/view-703663.html

发布于 : 2021-03-24 阅读(0)