Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >云原生家庭网络(十七):使用 nftables 透明拦截流量

云原生家庭网络(十七):使用 nftables 透明拦截流量

原创
作者头像
imroc
发布于 2024-05-30 01:57:13
发布于 2024-05-30 01:57:13
6180
举报

概述

iptables 和 nftables 都能用于透明代理的流量拦截,区别就是 nftables 是后起之秀,未来取代 iptables。可读性更高、性能更好。

本文介绍如何在路由器利用 nftables 透明拦截流量。

思路

可以利用 Pod 的 postStart 和 preStop 两个生命周期的 hook 来设置和清理 nftables 相关规则:

代码语言:yaml
AI代码解释
复制
        lifecycle:
          postStart:
            exec:
              command:
              - /scripts/set-rules.sh
          preStop:
            exec:
              command:
              - /scripts/clean.sh

脚本和 nftables 通过 configmap 挂载。

volumeMounts 部分:

代码语言:yaml
AI代码解释
复制
        volumeMounts:
        - mountPath: /scripts
          name: script
        - mountPath: /etc/nftables
          name: nftables-config

volumes 部分:

代码语言:yaml
AI代码解释
复制
      volumes:
      - configMap:
          defaultMode: 420
          name: nftables-config
        name: nftables-config
      - configMap:
          defaultMode: 511
          name: script
        name: script

另外,保险起见,可以加个 initContainer,保证在启动的时候也执行下清理规则的脚本(避免代理 Pod 异常挂掉导致 preStop 里的清理规则脚本没执行到):

代码语言:yaml
AI代码解释
复制
      initContainers:
      - command:
        - /scripts/clean.sh
        image: your-proxy-image
        imagePullPolicy: IfNotPresent
        name: clean
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /scripts
          name: script

nftables 规则

nftables.conf:

代码语言:conf
AI代码解释
复制
#!/usr/sbin/nft -f

table inet proxy
delete table inet proxy

table inet proxy {

    # 保留网段,参考:https://zh.wikipedia.org/zh-sg/%E4%BF%9D%E7%95%99IP%E5%9C%B0%E5%9D%80
    set byp4 {
        typeof ip daddr
        flags interval
        elements = {
            0.0.0.0/8,
            10.0.0.0/8,
            100.64.0.0/10,
            127.0.0.0/8,
            169.254.0.0/16,
            172.16.0.0/12,
            192.0.0.0/24,
            192.0.2.0/24,
            192.88.99.0/24,
            192.168.0.0/16,
            198.18.0.0/15,
            198.51.100.0/24,
            203.0.113.0/24,
            224.0.0.0/4,
            240.0.0.0-255.255.255.255
        }
    }
    set byp6 {
        typeof ip6 daddr
        flags interval
        elements = {
            ::,
            ::1,
            ::ffff:0:0:0/96,
            100::/64,
            64:ff9b::/96,
            2001::/32,
            2001:10::/28,
            2001:20::/28,
            2001:db8::/32,
            2002::/16,
            fc00::/7,
            fe80::/10,
            ff00::/8
        }
    }

    chain prerouting {
        type filter hook prerouting priority filter; policy accept;

        meta l4proto != { tcp, udp } counter return

        # 避免拦截公网回包(如果没用主路由方案,可以删除)
        iifname ppp0 \
          ct state new \
          ct mark set 11 \
          log prefix "Public Inbound:" \
          counter \
          return \
          comment "Mark conntrack for connection from internet, avoid intercept the return packets"

        # 不拦截从公网主动进来的包(如果没用主路由方案,可以删除)
        iifname ppp0 counter return

        # 避免源和目的都是本机公网 IP 时造成代理 UDP 无限回环
        fib daddr type local counter return

        # 对保留 IP(包括内网) 放行。
        ip daddr @byp4 counter return
        ip6 daddr @byp6 counter return
        goto proxy
    }
    chain proxy {
        # 对其它数据包(其它内网机器访问公网的包)进行拦截,全部转发给代理。
        # 踩坑:一定 tproxy 到回环 ip (127.0.0.1和::1),如果 tproxy 到 0.0.0.0和::,运行一段时间后,可能会导致 UDP 疯狂不停回环打满 CPU(本机外部IP到本机外部IP一直在lo网卡打转)
        meta l4proto { tcp, udp } tproxy ip to 127.0.0.1:12345 meta mark set 1 counter
        meta l4proto { tcp, udp } tproxy ip6 to [::1]:12345 meta mark set 1 counter
    }
    chain output {
        type route hook output priority filter; policy accept;

        # 不拦截代理自身发出的包。
        meta skgid eq 23333 counter return

        # 不拦截公网回包
        ct mark 11 counter return

        # 对保留 IP(包括内网) 放行。
        ip daddr @byp4 counter return
        ip6 daddr @byp6 counter return

        # 避免源和目的都是本机公网 IP 时造成代理 UDP 无限回环
        fib daddr type local counter return

        # 主机内进程发出的包打上 mark,让报文走策略路由重新进入 PREROUTING,以便被代理。
        meta l4proto { tcp, udp } meta mark set 1 counter
    }
}

设置规则的脚本

set-rules.sh:

代码语言:bash
AI代码解释
复制
#!/bin/bash

set -x

while :; do
	export https_proxy=http://127.0.0.1:10809                                           # 假设代理会启动 10809 端口的 HTTP 代理
	code=$(curl -I -o /dev/null -m 5 -s -w %{http_code} https://www.google.com | xargs) # 通过代理探测目标地址是否正常响应
	if [[ "${code}" == "200" ]]; then                                                   # 探测成功就退出探测循环,准备设置策略路由
		break
	fi
	echo "bad code:${code};" >/tmp/error.log
	sleep 5s
done

echo "proxy is ready, set up rules"
ip rule list | grep "from all fwmark 0x1 lookup 100"
if [ $? -ne 0 ]; then
	echo "add rule and route"
	ip rule add fwmark 0x1 table 100
	ip route add local 0.0.0.0/0 dev lo table 100
	ip -6 rule add fwmark 0x1 table 100
	ip -6 route add local ::/0 dev lo table 100
fi

nft -f /etc/nftables/nftables.conf # 设置 nftables 规则
exit 0

清理规则的脚本

clean.sh:

代码语言:bash
AI代码解释
复制
#!/bin/bash

set -x

nft delete table inet proxy # 关闭时清理 nftables,避免拉不了镜像
ip rule delete fwmark 0x1 table 100
ip route delete local 0.0.0.0/0 dev lo table 100
ip -6 rule delete fwmark 0x1 table 100
ip -6 route delete local ::/0 dev lo table 100

exit 0

定向拦截

如果家里的设备特别多,全局拦截流量的话,对代理的压力可能较大,有时可能会影响网速。

这种情况可以考虑只拦截特定设备的流量,比如只拦截 10.10.10.2~10.10.10.10 这个小网段的流量,该网段的 IP 可以静态分配,在 dnsmasq 的 dhcp 里配一下,示例:

代码语言:conf
AI代码解释
复制
log-queries=extra
no-resolv
no-poll
server=61.139.2.69
strict-order
log-dhcp
cache-size=2000
dhcp-range=10.10.10.11,10.10.10.254,255.255.255.0,12h
dhcp-authoritative
dhcp-leasefile=/var/lib/dnsmasq/dnsmasq.leases
dhcp-option=option:router,10.10.10.2
dhcp-option=option:dns-server,61.139.2.69,218.6.200.139
dhcp-host=a0:78:17:87:0e:51,10.10.10.5 # M1
dhcp-host=fc:18:3c:37:6a:1c,10.10.10.6 # iPhone - roc
  • dhcp-host 配置项里填入设备的 MAC 地址及其对应固定分配的 IP 地址。

需要注意的是,有些设备在内网通信时可能不会使用真实的 MAC 地址,比如 iPhone,可以在无线局域网里点进连上的 WiFi 设置下,关掉 私有无线局域网地址

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
nftables初体验
之前一直耳闻 nftables 是下一代 iptables 。前段时间配了一台主机,折腾成家里的软路由。就一并来尝鲜一系列新东西,其中就包括 nftables 。nftables 和 iptables 、ebtables 等一样,都是对底层 xtables 的封装,目前看来 nftables 比 iptables 更简洁易用,更易读,更容易理解,扩展性和也更好。但是目前各个发行版中对 nftables 的支持还比较参差不齐,导致 nftables 很多功能比 iptables 还是有所缺失,所以个人感觉短期内还是替代不了 iptables (比如 tproxy 功能需要 linux kernel 4.19+, 而即便是 CentOS 8 的内核版本也只是 4.18 ,所以都不支持 )。 nftables 所支持的功能列表及所以来的内核版本和内核模块可以在这里找到 https://wiki.nftables.org/wiki-nftables/index.php/Supported_features_compared_to_xtables 。
owent
2020/02/18
7.3K0
折腾一下nftables下的双拨
我们小区终于有联通线路啦,之前一直用的联通的手机号。它套餐满一定额度以后送一条宽带,本着不用白不用的精神,那必须不能浪费。还好我之前设置软路由得时候就预留了两个网口作wan,所以新增得联通得线路直接插那个口上就行了。(吐槽一下联通给得光猫竟然是8年前生产的老古董)
owent
2023/03/17
2.4K0
折腾一下nftables下的双拨
云原生家庭网络(二):基础网络配置
软路由需要配置一个静态 IP 和一个默认路由,Ubuntu 可以使用 netplan 来配置,配置文件路径是 /etc/netplan/config.yaml,通过 netplan apply 执行生效。下面根据不同方案给出一些配置示例。
imroc
2024/05/14
3560
云原生家庭网络(二):基础网络配置
探索:适用IPv6、Fullcone NAT的旁路由透明代理方案
最近由于考试周临近,所以博客这边都没怎么更新,这回逮到机会赶紧更一篇。我其实一直有个需求,就是想在学校也能无缝接入家里的网络,访问NAS之类的设备,因此我一直想设置一个透明代理。于是最近断断续续研究了几天,总算是摸索出了一个让自己相对满意的透明代理方案,因此就抽空写了篇博客,权当记录。事先说明:这篇博客仅仅描述了一个透明代理方案,并不包含任何代理服务器搭建的内容。方案的大致结构如下图,具体细节和配置我会在后文中详叙。
KAAAsS
2022/01/14
6.7K0
探索:适用IPv6、Fullcone NAT的旁路由透明代理方案
nftables用法介绍
Kubernetes 1.29版本中已经将nftables作为一个featureGates,本文简单整理了nftables的用法,便于后续理解kubernetes的nftables规则。文末给出了使用kubeadm部署启用nftables featureGates的配置文件。
charlieroro
2024/01/31
2K0
让 Linux 防火墙新秀 nftables 为你的 VPS 保驾护航
上篇文章 给大家介绍了 nftables 的优点以及基本的使用方法,它的优点在于直接在用户态把网络规则编译成字节码,然后由内核的虚拟机执行,尽管和 iptables 一样都是基于 netfilter,但 nftables 的灵活性更高。
米开朗基杨
2019/12/23
4.1K0
彻底弄懂Service Mesh透明代理 TPROXY
在现代微服务架构中, Service Mesh 作为基础设施层为服务间通信提供了强大支持,其中透明代理是一项关键技术,这篇文章做了一个比较细致的分析,彻底弄懂 TPROXY 透明代理/REDIRECT 的技术细节,涉及到下面这些内容:
挖坑的张师傅
2024/07/05
1.6K0
彻底弄懂Service Mesh透明代理 TPROXY
nftables 日志解决方案实践
根据官方 wiki 中Logging traffic[1]这篇文章的说明:从 Linux 内核 3.17 开始提供完整的日志支持。如果您运行较旧的内核,则必须 modprobe ipt_LOG 以启用日志记录。从 nftables v0.7 开始,支持 log 标志。
米开朗基杨
2021/07/15
2.7K0
GNU/Linux 系统下 nftables 防火墙的本地 IPS 能力部署实例
随着各 GNU/Linux 系统厂商以及社区逐步开始采用新的内核作为其发行版本的默认内核,防火墙机制采用了更新的 nftables 防火墙机制。
用户8639654
2021/09/18
1.2K0
CentOS 8 都发布了,你还不会用 nftables?
如果你没有生活在上个世纪,并且是云计算或相关领域的一名搬砖者,那你应该听说最近 CentOS 8 官方正式版已经发布了,CentOS 完全遵守 Red Hat 的再发行政策,并且致力与上游产品在功能上完全兼容。CentOS 8 主要改动和 RedHat Enterprise Linux 8 是一致的,基于 Fedora 28 和内核版本 4.18,其中网络方面的主要改动是用 nftables 框架替代 iptables 框架作为默认的网络包过滤工具。如果你还没有听说过 nftables,现在是时候学习一下了。
米开朗基杨
2019/10/09
1.8K0
又开新坑之 coredns 插件: nftables和filter
传说中的下一代 iptables 的 nftables 已经出来了好长时间了。现在主流发行版的内核也都已经更新到了对 nftables 支持足够好的版本。 在2年多前我也初步体验过了 nftables ,当时写了个 《nftables初体验》 。并且开始使用 nftables 来实现对家里软路由的管理。 而去年的时候,我也尝试用 nftables 实现了双拨(详见: 《折腾一下nftables下的双拨》)并且可以搭配TPROXY透明代理使用。
owent
2023/03/06
1.3K0
Haproxy实现Exchange全透明代理服务
公司最近Exchange邮件系统来构建高可用邮件系统架构。前端负载均衡就是使用了微软的NLB来实现cas的负载均衡。但是方案实施工程中也发现了一些问题,使用NLB在网络中产生大量广播报,出现丢包严重问题。后改用haproxy替代NLB实现cas的负载均衡,但也这就导致了一个问题,最明显的就是用户通过Haproxy来访问邮件系统后 真正达到邮件系统的地址都是Haproxy的地址,在垃圾邮件过滤的时候就无法实现基于IP的过滤,并且也无法记录IP地址信息。为 了解决这个问题我google了很多方案,可以使用硬负载,硬负载可以实现全透明代理让后端邮件服务器获取到用户的真实IP,还有一种解决方案就是 Haproxy的全透明代理。接下来将会介绍下Haproxy的全透明代理的部署。
星哥玩云
2022/07/03
1.1K0
Haproxy实现Exchange全透明代理服务
思科VPP系列砖题:如何使用vpp构建家庭网关
VPP 平台是一个可扩展的框架,可提供开箱即用的生产质量交换机 / 路由器功能。它是思科矢量数据包处理(Vector Packet Processing,VPP)技术的开源版本:一种高性能的数据包处理堆栈,可以在商用 CPU 上运行。
通信行业搬砖工
2023/09/07
9990
思科VPP系列砖题:如何使用vpp构建家庭网关
代理模式下获取客户真实IP
我们经常会在我们后端服务前加一层代理去做负载均衡或认证,比较有名的就是apisix。但是,这样会出现一些问题,比如说后端服务无法获取到客户真实的ip,显示的都是代理的ip,对于业务展示会有问题。对于7层的后端服务还好,可以在载荷里将客户的出口ip带上来,但是四层和三层就不太容易了,目前主流的有下面两种解决方案:
于顾而言SASE
2024/11/14
2430
代理模式下获取客户真实IP
Udp的反向代理:nginx
在实时性要求较高的特殊场景下,简单的UDP协议仍然是我们的主要手段。UDP协议没有重传机制,还适用于同时向多台主机广播,因此在诸如多人会议、实时竞技游戏、DNS查询等场景里很适用,视频、音频每一帧可以允许丢失但绝对不能重传,网络不好时用户可以容忍黑一下或者声音嘟一下,如果突然把几秒前的视频帧或者声音重播一次就乱套了。使用UDP协议作为信息承载的传输层协议时,就要面临反向代理如何选择的挑战。通常我们有数台企业内网的服务器向客户端提供服务,此时需要在下游用户前有一台反向代理服务器做UDP包的转发、依据各服务器的实时状态做负载均衡,而关于UDP反向代理服务器的使用介绍网上并不多见。本文将讲述udp协议的会话机制原理,以及基于nginx如何配置udp协议的反向代理,包括如何维持住session、透传客户端ip到上游应用服务的3种方案等。
陶辉
2019/06/21
12.1K0
Udp的反向代理:nginx
Istio 中实现客户端源 IP 的保持
尹烨,腾讯专家工程师, 腾讯云 TCM 产品负责人。在 K8s、Service Mesh 等方面有多年的实践经验。 导语 对于很多后端服务业务,我们都希望得到客户端源 IP。云上的负载均衡器,比如,腾讯云 CLB 支持将客户端源IP传递到后端服务。但在使用 istio 的时候,由于 istio ingressgateway 以及 sidecar 的存在,后端服务如果需要获取客户端源 IP,特别是四层协议,情况会变得比较复杂。 正文 很多业务场景,我们都希望得到客户端源 IP。云上负载均衡器,比如,腾讯云 C
腾讯云原生
2022/06/08
2.7K0
Istio 中实现客户端源 IP 的保持
【Linux】《how linux work》第九章 了解网络及其配置(2)
There are several ways to automatically configure networks in Linux-based systems. The most widely used option on desktops and notebooks is NetworkManager. Other network configuration management systems are mainly targeted for smaller embedded systems, such as OpenWRT’s netifd, Android’s ConnectivityManager service, ConnMan, and Wicd. We’ll briefly discuss NetworkManager because it’s the one you’re most likely to encounter. We won’t go into a tremendous amount of detail, though, because after you see the big picture, NetworkManager and other configuration systems will be more transparent
阿东
2024/04/27
2080
【Linux】《how linux work》第九章 了解网络及其配置(2)
【Linux】《how linux work》第九章 了解网络及其配置
Networking is the practice of connecting computers and sending data between them. That sounds simple enough, but to understand how it works, you need to ask two fundamental questions:
阿东
2024/04/22
3200
【Linux】《how linux work》第九章 了解网络及其配置
learning:Wireguard plugin
本文主要介绍wireguard的vpp的基本配置与转发流程,其他相关wireguard原理及理论实现可以阅读参考文章。
dpdk-vpp源码解读
2023/01/04
2.3K0
learning:Wireguard plugin
十二.Linux网络管理
在/etc/sysconfig/network-scripts/目录下有不少文件,绝大部分都是脚本类的文件,但有一类ifcfg开头的文件为网卡配置文件(interface config),所有ifcfg开头的文件在启动网络服务的时候都会被加载读取,但具体的文件名ifcfg-XX的XX可以随意命名。
对弈
2019/09/04
2.9K0
相关推荐
nftables初体验
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档