iptables规则绑定在port而不是拦截在协议栈

本文探讨了Linux Netfilter与Cisco设备ACL的不同之处,并提出了一种改进方案,通过模仿Cisco方式将规则绑定到设备上,以此提高数据包过滤效率。
版权声明:本文为博主原创,无版权。未经博主同意能够任意转载,无需注明出处,任意改动或保持可作为原创!

https://blog.youkuaiyun.com/dog250/article/details/24173103

是不是要又一次设计Netfilter的HOOK点位置了?无疑这是一个没有意义的问题,由于你无法证明新的方案更好。你可能仅仅是看上了还有一个平台的方案而已。而这个方法和Netfilter的方案是不同的。

其实,我就是这样一个人。
       Cisco的ACL能够被编译在port上。其实Cisco设备的网络port角色是能够被定义的,Linux的理念和此全然不同,Linux内核觉得定义角色这样的事是用户态的职责。如何要实现一个具有完备性的,不依赖用户态配置的数据包拦截机制,那就必须在协议栈路径上进行拦截。换句话说。Netfilter是全然基于skb本身来拦截并处理数据包的,这一点能够从NF_HOOK宏的參数看得出来,可是你能够看到。它还有两个net_device參数。基于这一点,我们就能够模仿Cisco设备的方式将规则绑定到设备了,这么做是有优点的,能够大大提高效率。

比方假设你配置了10000条规则,假设有不相关网口设备进来的数据包。那么这些数据包就不必经过iptables规则的过滤。
       须要改动的地方比較少,这里仅仅给出ipt_hook的改动:

static unsigned int
ipt_hook(unsigned int hook,
         struct sk_buff *skb,
         const struct net_device *in,
         const struct net_device *out,
         int (*okfn)(struct sk_buff *))
{

        struct netns_table_per_dev {
                struct list_head list;
                struct net_device *dev;
                struct xt_table *table;
        };
        // dev_net(in)->ipv4.iptable_filter不再是一个xt_table,而是一个list
        struct wrap_table {
                struct list_head *tb_list;
        };
        struct xt_table *table;
        struct netns_table_per_dev *table_dev;
        struct list_head *pos;
        struct wrap_table *tb_list = (struct wrap_table *)dev_net(in)->ipv4.iptable_filter;
        list_for_each(pos, tb_list->tb_list) {
                table_dev = list_entry(pos, struct netns_table_per_dev, dev);
                if (table_dev->dev == in) {
                        table = table_dev->table;
                }
        }
        if (table == NULL) {
                return NF_ACCEPT;
        }
        return ipt_do_table(skb, hook, in, out, table);
}
一个在协议栈拦截。一个在设备拦截,该手术做的有点大。颠覆了既有的理念。不知道会不会有后遗症。


       无论如何,不能走火入魔。

转载于:https://www.cnblogs.com/xfgnongmin/p/10670341.html

from netfilterqueue import NetfilterQueue from scapy.all import IP, TCP import subprocess import logging # 配置日志 logging.basicConfig(level=logging.DEBUG) # 数据包数组 packet_queue = [] # 存储拦截的数据包 queue_length = 5 # 队列长度阈值 # 定义数据包处理函数 def process_packet(packet): global packet_queue global queue_length logging.debug(f"拦截到一个数据包,大小:{len(packet.get_payload())}") scapy_packet = IP(packet.get_payload()) # 将数据包转换为 Scapy 对象 # 检查 TCP 标志 if scapy_packet.haslayer(TCP): tcp_flags = scapy_packet[TCP].flags if tcp_flags & 0x02: # SYN 标志为 1 logging.debug("SYN 标志为 1,正常发送数据包") packet.accept() elif tcp_flags & 0x01: # FIN 标志为 1 logging.debug("FIN 标志为 1,正常发送数据包") packet.accept() else: # 将数据包存入队列 packet_queue.append(packet) # 如果队列中有足够的数据包,重新排序并发送 if len(packet_queue) >= queue_length: # 假设我们每次处理 5 个数据包 print("发送数据包") sorted_packets = sorted(packet_queue, key=lambda p: p.get_timestamp()) # 按时间戳排序 for p in sorted_packets: p.accept() # 释放数据包,发送到下一个处理阶段 packet_queue = [] # 清空队列 # 如果队列未达到阈值,直接返回 return else: packet.accept() # 如果不是 TCP 数据包,则直接通过 # 设置 iptables 规则 def setup_iptables(port, queue_num): logging.debug(f"设置 iptables 规则,将端口 {port} 的数据包转发到队列 {queue_num}...") try: subprocess.run([ "sudo", "iptables", "-I", "OUTPUT", "-p", "tcp", "--sport", str(port), "-j", "NFQUEUE", "--queue-num", str(queue_num) ], check=True) except subprocess.CalledProcessError as e: logging.error(f"Error setting iptables rules: {e}") # 清理 iptables 规则 def cleanup_iptables(): logging.debug("清理 iptables 规则...") try: subprocess.run(["sudo", "iptables", "-F"], check=True) except subprocess.CalledProcessError as e: logging.error(f"Error cleaning up iptables rules: {e}") # 主函数 def main(): port = 8080 # 监听的端口 queue_num = 0 # NetfilterQueue 队列编号 try: # 设置 iptables 规则 setup_iptables(port, queue_num) # 创建 NetfilterQueue 对象并绑定到队列编号 nfqueue = NetfilterQueue() nfqueue.bind(queue_num, process_packet) logging.debug(f"开始监听端口 {port} 的数据包...") try: nfqueue.run() except KeyboardInterrupt: logging.debug("停止监听...") except Exception as e: logging.error(f"Error in NetfilterQueue: {e}") finally: nfqueue.unbind() cleanup_iptables() except Exception as e: logging.error(f"Error in main: {e}") if __name__ == "__main__": main() 该代码是否能够达到拦截并存储数据包,然后顺序发送的目的
最新发布
04-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值