range内核端口数据转发模块
NGINX 向云原生演进,All inOpenNJet range 端口转发模块 1.1 需求 在很多时候,比如流量劫持、ftp被动模式代理等功能需要能够支持流量端口转发。比如需要将10000到11000端口范围的所有流量都统一转到12000端口上,然后在12000端口上接收所有的报文进行后续处理。 1.2 依赖 该功能的实现依赖于iptables,如果通过rpm包安装,则自动为privilege进程为root启动 如果是普通用户启动,需要对opennjet设置setuid权限 setcap cap_setuid=eip /home/njet/sbin/njet 1.3 指令设计 Syntax range type={tcp|udp} src_ports={port1:port2} dst_port={dst_port}; 如果默认iptables path为/usr/sbin/iptables, 如果系统iptables路径不是这个,需要指定使用如下指令 range iptables_path={iptables_path}; Default - Context Core, 支持配置多条 参数说明: 参数 类型 必填 默认值 说明 type string 否 tcp [tcp|udp], 指明是tcp还是udp数据,默认tcp src_ports string 是 - 支持单端口或者端口范围,格式如下: 端口范围(冒号分隔): 11000:12000 一个端口: 11000 dst_port int 是 - 目标端口 iptables_path string 否 /usr/sbin/iptables 这个根据系统而定,调用system执行的时候可能会出现找不到iptables错误,这个时候需要看看对应系统的iptables path,然后设置一下这个参数 如果配置多条range指令,则以最后一个明确指定的iptables_path为准 配置示例(tcp为例): 将发往本机端口为11000到12000范围的数据,转发到13000端口: range type=tcp src_ports=11000:12000 dst_port=13000 将发往本机端口为11000,转发到13000端口: range type=tcp src_ports=11000 dst_port=13000 设置iptables path为/usr/sbin/iptables range iptables_path=/usr/sbin/iptables; 1.4 实现方案 本功能的实现借助于iptables规则,通过range指令解析参数,然后生成对应的iptables规则下发。 range指令支持配置多条规则 模块init的时候会根据规则生成iptables规则 模块exit的时候会将规则进行删除 所有的规则都会放到自定义iptables链 OPENNJET上 1.5 测试 1.5.1 配置示例 njet.conf 配置里配置两条range指令 ... load_module modules/njt_range_module.so; #加载range模块... user nobody; events { worker_connections 1024; } error_log logs/error_privilege.log info;#配置两条range指令range type=tcp src_ports=11000:12000 dst_port=13000;range type=tcp src_ports=10000 dst_port=14000;#默认路径为/usr/sbin/iptables, 如果系统路径不一致需要调用该指令设置下路径range iptables_path=/usr/sbin/iptables;http { access_log logs/access_privilege.log combined; include mime.types; server { ... } } cluster_name helper; node_name node1; 1.5.2 测试结果 启动OpenNJet前 查询系统iptables 规则: 启动OpenNJet后 重新查询iptables规则,发现两条规则生效 reload重启后 重新查询,发现两条规则还在 停止OpenNJet后 重新查询,两条规则删除 2. 命令式 API动态配置端口转发规则 2.1 需求: 能够通过api接口查询全量的range 配置规则 能够通过api增加或者删除一条range配置规则 根据type、src_ports、dst_port三个字段来确定一条规则 2.2 配置 ctrl控制面配置: ...load_module modules/njt_http_range_api_module.so; #load range api module ... server { listen 8081; location /range { dyn_range_api; #配置range api开关 } } ... 2.3 动态API 查询: GET http://192.168.40.136:8081/range { "ranges": [ { "type": "tcp", "src_ports": "11000:12000", "dst_port": 10001 }, { "type": "tcp", "src_ports": "10000", "dst_port": 14000 } ] } PUT http://192.168.40.136:8081/range #添加一条规则 { "action": "add", "type": "tcp", "src_ports": "11000:13000", "dst_port": 10001 } #删除一条规则 { "action": "del", "type": "tcp", "src_ports": "11000:13000", "dst_port": 10001 } 参数 类型 必填 默认值 说明 action string 是 - [add|del] type string 是 - [tcp|udp], 指明是tcp还是udp数据 src_ports string 是 - 支持单端口或者端口范围,格式如下: 端口范围(冒号分隔): 11000:12000 一个端口: 11000 dst_port int 是 - 目标端口 return: { "code": 0, #0 表示成功, 非0 表示失败 "msg": "success" } 错误码 code msg 描述 0 success 成功 2 - 内存分配失败相关的一些错误信息 4 rule is not found 删除一个不存在的规则 4 rule has exist 添加一个已经存在的规则 4 其他错误 2.4 swagger访问 可以通过doc模块提供的swagger界面操作 http://192.168.40.136:8081/doc/swagger/ 2.5 测试 通过swagger页面进行api测试 初始状态get 查询配置 查询iptables 通过swagger页面添加一个规则 再次 查询配置和iptables reload后再次查询,动态添加的配置和iptables都存在刚才动态添加的配置 Stop OpenNJet后,iptables规则消失 OpenNJet 最早是基于 NGINX1.19 基础 fork 并独立演进,具有高性能、稳定、易扩展的特点,同时也解决了 NGINX 长期存在的难于动态配置、管理功能影响业务等问题。邮件组官网