Chion82 / netfilter-full-cone-nat

A kernel module to turn MASQUERADE into full cone SNAT
GNU General Public License v2.0
427 stars 121 forks source link

映射端口冲突及端口随机化问题 #2

Closed Chion82 closed 6 years ago

Chion82 commented 6 years ago

关于端口冲突,和 --random 的问题统一在该issue中讨论。

https://github.com/Chion82/netfilter-full-cone-nat/commit/a3c4615cddecee002542613e2d56990e7f4f20d7 修复了 --random 的出站方向二次映射的端口分配不一致的问题。

更新: 针对未使用 --random 的情况,解决如下case的冲突:

内网主机A到外网B,建立NAT映射到5000端口(A:5000->NAT:5000->B:100); 内网主机C到公网D,建立NAT映射到5000端口(C:5000->NAT:5000->D:100);

https://github.com/Chion82/netfilter-full-cone-nat/commit/9c643b78cc40eaeacdafb8691d1ec26f5ee26f9e 新增了mappings表老化检测机制和“临时的冲突解决”(如遇到冲突的情况,使用端口随机化)

TODO: 使用 端口随机化 解决映射端口冲突仍有小的概率再次遇到冲突,是否需要改进为:遍历 mapping_table 表来获得确定性的无冲突端口? 如果需要改进为这种方案,需要参考 nf_nat_l4proto_unique_tuple() 的实现,在本模块中完成所有的端口分配计算,修改量较大,是否有必要采用这种方案。

Chion82 commented 6 years ago

在 #3 中引入了“在本模块中管理全部端口分配”,可解决所有的冲突case。

xd5520026 commented 6 years ago

@Chion82 1、关于mapping表老化问题: 新增加的clear_inactive_mappings函数每当进入该模块函数时都要遍历一遍mapping表并逐一检查conntrack表是否失效,这种检查有点太影响性能了。是不是可以在get_mapping函数里实现,当在mapping表里查到映射时调用is_mapping_active函数判断一下,失效就老化删除。

2、关于mapping表的查找: 在get_mapping_by_original_src函数中调用hash_for_each遍历整个mapping表时间复杂度也是O(n)线性的,这个地方是不是可以优化一下。

Chion82 commented 6 years ago

@xd5520026 近两日对这个模块做了大量的重构调整,增加了对各种case的支持(多网卡接口、多tuple跟踪及mapping引用计数等), 你说的这两个问题都解决了:

  1. 使用了“注册conntrack事件回调”来辅助mapping表老化(在仔细阅读conntrack源码的时候终于发现了之前一直在找的 nf_conntrack_register_notifier )。不过这个调整 依赖内核编译时打开 CONFIG_NF_CONNTRACK_EVENTS(x86发行版大多数默认开启,ARM等设备可能未默认打开)。
  2. 建立了多索引

新增的feature可能还有不少问题,目前仍在调整开发和完善中。

xd5520026 commented 6 years ago

@Chion82 1、在3.18内核上编译报错nf_ct_zone函数没有定义,添加 #include <net/netfilter/nf_conntrack_zones.h>通过。 2、该模块依赖的很多内核空间函数,我在老版本内核源码里编译不通过,建议做一个版本说明。

Chion82 commented 6 years ago

@xd5520026

  1. 缺失的头文件已经修复了。
  2. 内核模块对内核版本的兼容一直是头疼的问题,我也只在4.9以上(openwrt当前的snapshot版本)的内核版本做过测试。要找到这个模块最低兼容到哪个内核版本确实比较麻烦。

想确认一下,3.18确认可以编译通过了吗?不通过的版本是多少?

xd5520026 commented 6 years ago

@Chion82

  1. 现在内核模块在centos7(kernel-3.10)和kernel-3.18上编译通过,但在kernel-2.6.32上编译失败。简单查看了下主要是老版本内核不支持nf_conntrack_zone。还有部分内核版本不支持NF_NAT_RANGE_PROTO_RANDOM_FULLY选项
  2. 在iptables-1.4.21编译iptables模块也不支持NF_NAT_RANGE_PROTO_RANDOM_FULLY,看可不可以对NF_NAT_RANGE_PROTO_RANDOM_FULLY加个宏判断
  3. 我在openwrt上增加这两个模块也遇到了不少问题,能不能增加一个在openwrt上编译此模块的简单说明以方便其他人的使用
ZhYuLn commented 6 years ago

@Chion82 您好,我发现我在使用fullconenat模块的时候,系统在运行一段时间之后会在内核提示nf_conntrack: table full, dropping packet,我只对了系统的udp数据做cone nat,请问下这个可以用什么方式来避免

dzxx36gyy commented 6 years ago

@Chion82 使用4.9内核配合最新的iptables(20180429)进行编译,发现有流量的情况下(视使用可能在最短几个小时最长一天多)会导致内核卡死……不知道是否是端口冲突或者其他导致的呢?

tingjunli commented 5 years ago

@Chion82 我在linux内核3.18.29中编译时,添加了CONFIG_NF_CONNTRACK_EVENTS选项,但是insmod时依然报错,可能还有什么其它的选项没有开吗? xt_FULLCONENAT: warning: failed to register a conntrack notifier. Disable active GC for mappings.

flyhigao commented 4 years ago

翻历史老贴,我也遇到类似问题,在ledeOP上开启zerotier,在内网某台服务器也开启zerotier,由于二者都是监听9993端口。OP上启动fullcone。于是内网服务器过一段时间的zerotier服务就会下线,所有planet都连不上了