Tag: pbr

  • VyOS Debug PBR & NAT

    As ROOT.

    Keyword: nftrace

    Edit VyOS generated NFT files: /run/nftables*.

    Enable nftrace on full chain

    table ip vyos_mangle {
        chain VYOS_PBR_PREROUTING {
            type filter hook prerouting priority -150; policy accept;
            meta nftrace set 1
            iifname { eth2,eth0 } counter jump VYOS_PBR_UD_MY_PBR_RULES
        }
    }

    Make sure nftrace is enabled before other rules!

    Enable nftrace on SINGLE RULE.

    table ip vyos_mangle {
        chain VYOS_PBR_PREROUTING {
            type filter hook prerouting priority -150; policy accept;
            iifname { eth2,eth0 } counter jump VYOS_PBR_UD_MY_PBR_RULES
        }
    
        chain VYOS_PBR_UD_MY_PBR_RULES {
            ip saddr  @A_SRC_HIJACK_MITMPROXY counter meta mark set 2147483628 meta nftrace set 1 return comment "ipv4-route-ROUTE_CLASH_TUN-50"
        }
    }

    Test & Apply

    # Test
    nft --check --file /run/nftables_policy.conf
    # Apply
    nft --file /run/nftables_policy.conf

    Monitor

    nft monitor trace 

    Example Result

    trace id 0abb78f9 ip vyos_mangle VYOS_PBR_PREROUTING packet: iif "eth2" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 192.168.27.1 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_static_nat PREROUTING packet: iif "eth2" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 192.168.27.1 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_nat PREROUTING packet: iif "eth2" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 192.168.27.1 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_conntrack PREROUTING_HELPER packet: iif "eth2" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip raw VYOS_TCP_MSS packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_mangle VYOS_PBR_FORWARD packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 inet mangle FORWARD packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip protocol udp ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_filter VYOS_FORWARD_filter packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_filter VYOS_ZONE_FORWARD packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_mangle VYOS_PBR_POSTROUTING packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip nat VYOS_PRE_SNAT_HOOK packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
    trace id 0abb78f9 ip vyos_static_nat POSTROUTING packet: iif "eth2" oif "pppoe0" ether saddr bc:24:11:27:72:1b ether daddr bc:24:11:35:1c:c5 ip saddr 192.168.27.100 ip daddr 10.0.0.53 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 64190 ip length 68 udp sport 58012 udp dport 53 udp length 48 @th,64,96 0x990701200001000000000001
  • VyOS 实现LAN 流量劫持

    以前 EdgeRouter 时代,使用的是 DNAT + redsocks + charles/mitmproxy 实现的流量劫持和分析,比较麻烦的点是,redsocks的配置文件需要维护,服务需要重启,每次系统升级(虽然好多年没升级了)都需要重装 redsock,所以当时搞了一套初始化脚本,脱离config tree自动安装deb,自动加载配置,自动symlink配置文件。

    换到 VyOS 之后,本来也想搞这一套,被研发打回来了,他们不接受过分灵活的config tree,让我用 container。

    新方案用 hev-socks5-tunnel,直接把流量转给另外一台主机上的mitmproxy。charles proxy也可以用同样的方法配置

    开 mitmweb,方便web看数据

    mitmweb --web-host 0.0.0.0 --mode socks5 --listen-port 8889

    下列命令创建container,配置PBR

    set container name tun2socks allow-host-networks
    set container name tun2socks capability 'net-admin'
    set container name tun2socks device dev-net-tun destination '/dev/net/tun'
    set container name tun2socks device dev-net-tun source '/dev/net/tun'
    set container name tun2socks environment CONFIG_ROUTES value '0'
    set container name tun2socks environment IPV4 value '198.51.100.1'
    set container name tun2socks environment LOG_LEVEL value 'debug'
    set container name tun2socks environment MTU value '8500'
    set container name tun2socks environment SOCKS5_ADDR value '192.168.11.19'
    set container name tun2socks environment SOCKS5_PORT value '8889'
    set container name tun2socks environment SOCKS5_UDP_MODE value 'udp'
    set container name tun2socks environment TUN value 'tun9'
    set container name tun2socks image 'ghcr.io/heiher/hev-socks5-tunnel:latest'
    
    
    set protocols static table 19 description 'route to mitmproxy'
    set protocols static table 19 route 0.0.0.0/0 interface tun9
    
    set policy route PBR   interface 'eth2'
    set policy route PBR rule 50 set table '19'
    set policy route PBR rule 50 source group address-group 'SRC_HIJACK_MITMPROXY'
    
    
    # firewall rules ...

    防火墙规则需要自己搞定,按需NAT。

    nftables 不支持 ipset 那样动态操作成员了,只能在config tree里维护。

    这个方法和以前一样,只能去分析 TCP 协议。如果有 UDP 的需求可以尝试 WireGuard 的方式。

  • MITM 与 HTTPS 流量劫持

    VPS 硬盘挂之前,blog 里留了一篇文章,如何使用 redsocks + linux policy based routing 实现对手机 HTTPS 流量的劫持。具体方案懒得再写了。简单描述一下原理,后边的文章会需要引用。

    An illustration of the man-in-the-middle attack

    上图是引用自 Wikipedia 的中间人攻击的页面

    最古老的年代,通信缺少加密,所以中间传信的人可能能看到并篡改内容。后来,从算法保密,到算法公开密钥保密,再到后来 PKI 的出现,逐渐实现了相对安全的加密通信。

    但是,从开发、调试和安全研究的角度看,在拿不到 SSL/TLS 通信密钥的情况下,中间人攻击是协议调试的一个重要手段。(当然,如果能拿到 SSL/TLS 通信密钥,例如可以修改 SSL/TLS 握手的库,记录下来,就可以直接 tcpdump/wireshark 抓包,再用 wireshark 填入密钥就可以解密了。)

    加密通讯的中间人攻击,第一个典型场景的必要手段是让客户端信任中间人的证书,常见的手段:

    • 例如客户端不校验证书(签发者,时间,Common Name等),
    • 或者当客户端使用系统的方法和系统的 CA 库去校验的时候,安装自签的 CA 证书再用这个 CA 去签发被劫持的证书,
    • 甚至 Patch 的方式替换原有程序里写死的证书或证书策略(例如 Android)。

    第二个典型的必要手段是劫持流量,或者信道。常见的做法:

    • 如果被劫持的目标对象使用系统的代理,或者有代理设置的选项,修改这个选项。
    • 如果该目标不使用代理,但是系统平台有方法劫持,例如 proxifier(一个值得买的 win/mac 代理工具),使用 proxifier 可以按通讯地址端口或者进程名称将应用的流量。
    • 如果是不认代理设置的运行在封闭系统(iOS / Android)下的程序,就可以考虑网络设备上 NAT + redsocks 的方案将流量转到 Charles Proxy 或者 Fiddler 的 socks 代理上。
    • 其他的,例如 iOS/mac 的 Network Extension。。。

    近些年有些麻烦,一个是 Certificate Pinning,一个是 TLS 1.3。遇到自己实现的 Certificate Pinning,时间成本会上去,这里在越狱的 iOS 设备上推荐 https://github.com/nabla-c0d3/ssl-kill-switch2,可能大部分程序的检查都能绕过,FB 家的不行。TLS 1.3,如果自己实现的客户端不接受降级到 TLS 1.2或者更低,目前我无解,不知道有没有best practice。