Skip to content
This repository has been archived by the owner on Jan 26, 2024. It is now read-only.

The kernel itself can do this #12

Open
squarooticus opened this issue Nov 8, 2020 · 9 comments
Open

The kernel itself can do this #12

squarooticus opened this issue Nov 8, 2020 · 9 comments

Comments

@squarooticus
Copy link

In trying to debug my Google Cast issues last night, I discovered your daemon. It works great, presumably because it doesn't ingest and then create new mDNS payloads like avahi-daemon does. But then I realized nftables can do the same thing. To wit:

table ip mangle {
    chain prerouting {
        type filter hook prerouting priority mangle; policy accept;
        ip daddr 224.0.0.251 iif enp2s0.30 ip saddr set 192.168.1.1 dup to 224.0.0.251 device enp2s0.10 notrack
        ip daddr 224.0.0.251 iif enp2s0.10 ip saddr set 192.168.3.1 dup to 224.0.0.251 device enp2s0.30 notrack
    }
}

table ip6 mangle {
    chain prerouting {
        type filter hook prerouting priority mangle; policy accept;
        ip6 daddr ff02::fb iif enp2s0.30 ip6 saddr set fd20:1111:1111:1::1 dup to ff02::fb device enp2s0.10 notrack
        ip6 daddr ff02::fb iif enp2s0.10 ip6 saddr set fd20:1111:1111::3::1 dup to ff02::fb device enp2s0.30 notrack
    }
}

The above repeats mDNS packets from enp2s0.10 to enp2s0.30 and vice versa. Works great. Kinda nuts how simple this is.

@mmorrisontx
Copy link
Member

Definitely sounds like a more simple preferable option if you're on linux :). I'm stuck on pfsense, which is a BSD base.

@squarooticus
Copy link
Author

I can almost guarantee there's some way to get BPF to do this. IIRC, BPF is going to replace netfilter on Linux, with netfilter's full functionality emulated in BPF. But anyway, just thought you would be interested.

@mmorrisontx
Copy link
Member

Ahh, I don't have much experience with BPF. If anyone else has more experience I'd love to hear if it was possible. Obsoleting this package would be great, especially if it solves the split-udp packet issue.

@RichardHum
Copy link

RichardHum commented Dec 15, 2020

@squarooticus Thank you very much for finding this! I've been struggling with casting between my vlans. I'm having a little bit of trouble understanding what value to set the source ip of the mangled packet to. Is that source IP (192.168.1.1 and 192.168.3.1) the IP of the gateway on that lan? Or is the the IP of the interface on the relay?

Thanks!

@squarooticus
Copy link
Author

Yes, exactly. An address on the outgoing interface in the same subnet as the clients connected to that link. (For IPv4 in the usual case, that means the single IP address assigned to that interface. For IPv6, that means the link local address for that interface.)

@hogkite
Copy link

hogkite commented Feb 4, 2022

@squarooticus This looks very interesting and could be very useful, thx. Any idea what this rule would like in iptables? Do I need SNAT or TEE or something else, any guidance appreciated.

@squarooticus
Copy link
Author

squarooticus commented Feb 4, 2022

@hogkite Very likely TEE is the equivalent of dup. I don't know what the equivalent for changing the source address is, however: SNAT will change the source address, but may add an entry to the connection tracking table. It might not because the destination is a multicast address, but who knows? And even if it does, does it matter? So I would try that. Or take the time to switch to nftables: it's a lot nicer than iptables.

FWIW, my current implementation does this in two steps:

table ip mutate {
    chain repeat {
        type filter hook prerouting priority mangle;
        # mDNS repeat
        ip daddr 224.0.0.251 iifname $DMZ_IF ip saddr != $DMZ_IP dup to 224.0.0.251 device $LAN_IF notrack
        ip daddr 224.0.0.251 iifname $LAN_IF ip saddr != $LAN_IP dup to 224.0.0.251 device $DMZ_IF notrack
    }

    chain src_rewrite {
        type filter hook postrouting priority srcnat;
        # mDNS source rewriting
        ip daddr 224.0.0.251 oifname $LAN_IF ip saddr != $LAN_IP ip saddr set $LAN_IP ip ttl set 1 notrack
        ip daddr 224.0.0.251 oifname $DMZ_IF ip saddr != $DMZ_IP ip saddr set $DMZ_IP ip ttl set 1 notrack
    }
}

table ip6 mutate {
    chain mdns_repeat {
        type filter hook prerouting priority mangle;
        ip6 daddr ff02::fb iifname $DMZ_IF dup to ff02::fb device $LAN_IF notrack
        ip6 daddr ff02::fb iifname $LAN_IF dup to ff02::fb device $DMZ_IF notrack
    }

    chain mdns_src_rewrite {
        type filter hook postrouting priority srcnat;
        ip6 daddr ff02::fb oifname $LAN_IF ip6 saddr != $LAN_IP6_LL ip6 saddr set $LAN_IP6_LL notrack
        ip6 daddr ff02::fb oifname $DMZ_IF ip6 saddr != $DMZ_IP6_LL ip6 saddr set $DMZ_IP6_LL notrack
    }
}

I must have run into a problem or edge case with the previous implementation, but I honestly don't remember why I changed it.

@hogkite
Copy link

hogkite commented Feb 4, 2022

OK thanks for the update

@squarooticus
Copy link
Author

I just simplified it (FSVO "simplify").

table ip mutate {
    map iface_local_addr {
        type ifname : ipv4_addr;
        elements = {
            $LAN_IF   : $LAN_IP,
            $DMZ_IF   : $DMZ_IP
        }
    }

    chain repeat {
        type filter hook prerouting priority mangle;
        # mDNS repeat
        ip daddr 224.0.0.251 iifname { $LAN_IF, $DMZ_IF } counter mark set 2 dup to 224.0.0.251 device iifname map { $LAN_IF : $DMZ_IF, $DMZ_IF : $LAN_IF } notrack mark set 0
    }

    chain manglor {
        type filter hook postrouting priority srcnat;
        # mDNS source and TTL rewriting
        meta mark 2 ip saddr set oifname map @iface_local_addr ip ttl set 1 notrack
    }
}

table ip6 mutate {
    map iface_link_local_addr {
        type ifname : ipv6_addr;
        elements = {
            $LAN_IF   : $LAN_IP6_LL,
            $DMZ_IF   : $DMZ_IP6_LL
        }
    }

    chain repeat {
        type filter hook prerouting priority mangle;
        # mDNS repeat
        ip6 daddr ff02::fb iifname { $LAN_IF, $DMZ_IF } counter mark set 2 dup to ff02::fb device iifname map { $LAN_IF : $DMZ_IF, $DMZ_IF : $LAN_IF } notrack mark set 0
    }

    chain manglor {
        type filter hook postrouting priority srcnat;
        # mDNS source and hoplimit rewriting
        meta mark 2 ip6 saddr set oifname map @iface_link_local_addr ip6 hoplimit set 1 notrack
    }
}

I'll show myself out.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants