Open squarooticus opened 3 years ago
Definitely sounds like a more simple preferable option if you're on linux :). I'm stuck on pfsense, which is a BSD base.
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.
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.
@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!
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.)
@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.
@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.
OK thanks for the update
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.
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:
The above repeats mDNS packets from enp2s0.10 to enp2s0.30 and vice versa. Works great. Kinda nuts how simple this is.