Excellent! Will I even be able to use 3 or 4 VPNs? I just thought that for some ip subnets I want to use a different VPN.
OK it's not so well tested, but I have generalised out now. You can pull the latest files from:
For nftables I now have variables at the beginning in which you can define the interface names and IP addresses, and also MAC addresses for IoT devices to set to bulk. If you don't want to use the MAC addresses bit then just comment out the line lower down that uses this variable.
table inet cake-dual-ifb-inet
flush table inet cake-dual-ifb-inet
table bridge cake-dual-ifb-bridge
flush table bridge cake-dual-ifb-bridge
# local interfaces to collect traffic from
# ingress traffic through forward hook is sent to ifb-ul
# egress traffic through forward hook is sent to ifb-dl
define IFACE_NAMES = {
br-lan,
br-guest
}
# local interface IP addresses
# traffic with these destination addresses is skipped
define IFACE_IPS = {
192.168.1.1,
192.168.2.1
}
# local MAC addresses to set to bulk (e.g. IoT devices)
define BULK_MACS = {
XX,
YY
}
table inet cake-dual-ifb-inet {
chain hook-output {
type filter hook output priority filter
# OpenWrt->wan
oifname wan mark !=3 mark set 2 goto process-openwrt-to-wan
}
chain hook-forward {
type filter hook forward priority filter
# lan->wan
iifname $IFACE_NAMES goto process-lan-to-wan
# wan->lan
oifname $IFACE_NAMES goto process-wan-to-lan
}
chain hook-postrouting {
type filter hook postrouting priority filter
# fix ttl to help disguise use of router over mobile network
# for bridge mode set ttl to 64
# for USB tethering set ttl to 65
oifname wan ip ttl set 64
}
chain process-openwrt-to-wan {
jump classify-dscp
jump store-dscp-in-conntrack
# mark special bit '256' in conntrack for tc filtering on wan ingress
ct mark set ct mark or 256
}
chain process-lan-to-wan {
# Handle DNS hijacking (effectively resulting in openwrt-to-wan)
tcp dport 53 mark set 2 goto process-openwrt-to-wan
udp dport 53 mark set 2 goto process-openwrt-to-wan
}
chain process-wan-to-lan {
oifname $IFACE_NAMES mark set 1
# Handle DNS hijacking
tcp sport 53 mark set 0
udp sport 53 mark set 0
}
# OpenWrt->wan dscp classication by router
chain classify-dscp {
meta l4proto . th dport vmap @rules_proto_dport
}
map rules_proto_dport {
type inet_proto . inet_service : verdict
elements = {
tcp . 53 : goto dscp_set_voice, # DNS
udp . 53 : goto dscp_set_voice, # DNS
tcp . 853 : goto dscp_set_voice, # DNS-over-TLS
udp . 853 : goto dscp_set_voice, # DNS-over-TLS
udp . 123 : goto dscp_set_voice # NTP
}
}
# designate packet for cake tin: bulk
chain dscp_set_bulk {
ip dscp set cs1
}
# designate packet for cake tin: besteffort
chain dscp_set_besteffort {
ip dscp set cs0
}
# designate packet for cake tin: video
chain dscp_set_video {
ip dscp set cs2
}
# designate packet for cake tin: voice
chain dscp_set_voice {
ip dscp set cs4
}
chain store-dscp-in-conntrack {
# store DSCPs in conntracks
ip version 4 ct mark set (@nh,8,8 & 252) >> 2
ip6 version 6 ct mark set (@nh,0,16 & 4032) >> 6
ct mark set ct mark or 128
}
}
table bridge cake-dual-ifb-bridge {
chain hook-input {
type filter hook input priority filter
meta pkttype unicast ip daddr != $IFACE_IPS goto process-lan-to-wan
}
chain process-lan-to-wan {
ibrname $IFACE_NAMES mark set 1
# Handle DNS hijacking
tcp dport 53 mark set 0
udp dport 53 mark set 0
jump classify-dscp
goto store-dscp-in-conntrack
}
# lan->wan dscp classication by router
# set/override DHCP classifications on lan-originating traffic
chain classify-dscp {
meta l4proto . th dport vmap @rules_proto_dport
# IoT devices (put mac addresses here)
ibrname $IFACE_NAMES ether saddr $BULK_MACS goto dscp_set_bulk
}
map rules_proto_dport {
type inet_proto . inet_service : verdict
elements = {
udp . 123 : goto dscp_set_voice # NTP
}
}
# designate packet for cake tin: bulk
chain dscp_set_bulk {
ip dscp set cs1
}
# designate packet for cake tin: besteffort
chain dscp_set_besteffort {
ip dscp set cs0
}
# designate packet for cake tin: video
chain dscp_set_video {
ip dscp set cs2
}
# designate packet for cake tin: voice
chain dscp_set_voice {
ip dscp set cs4
}
chain store-dscp-in-conntrack {
# store DSCPs in conntracks
ip version 4 ct mark set (@nh,8,8 & 252) >> 2
ip6 version 6 ct mark set (@nh,0,16 & 4032) >> 6
ct mark set ct mark or 128
}
}
And then for the init.d script:
#!/bin/sh /etc/rc.common
exec &> /var/log/cake-dual-ifb.log
START=50
STOP=4
# local interfaces to combine flows from
ifaces="br-lan br-guest"
start()
{
# Setup dual IFBs
ip link add name ifb-ul type ifb
ip link add name ifb-dl type ifb
ip link set ifb-ul up
ip link set ifb-dl up
for iface in $ifaces; do
tc qdisc add dev $iface handle ffff: ingress
tc qdisc add dev $iface handle 1: root prio
# capture $if (ingress) -> wan
# filter on fwmark 1
tc filter add dev $iface parent ffff: protocol ip handle 1 fw flowid 1:1 action mirred egress redirect dev ifb-ul
# capture wan -> $iface (egress) and restore DSCPs from conntracks
# filter on fwmark 1
tc filter add dev $iface parent 1: protocol ip handle 1 fw flowid 1:1 action ctinfo dscp 63 128 action mirred egress redirect dev ifb-dl
done
tc qdisc add dev wan handle ffff: ingress
tc qdisc add dev wan handle 1: root prio
# capture OpenWrt -> wan (egress)
# filter by fwmark 2 (use nftables to skip over WireGuard traffic with fwmark 3 and apply fwmark 2 to the remainder)
tc filter add dev wan parent 1: protocol ip handle 2 fw flowid 1:1 action mirred egress redirect dev ifb-ul
# capture wan (ingress) -> OpenWrt and restore DSCPs from conntracks
# filter on conntrack bit 128 set
tc filter add dev wan parent ffff: prio 1 protocol ip matchall action ctinfo cpmark continue
tc filter add dev wan parent ffff: prio 2 protocol ip handle 256/256 fw flowid 1:1 action ctinfo dscp 63 128 action mirred egress redirect dev ifb-dl
# apply CAKE on the IFBs
tc qdisc add dev ifb-ul root cake bandwidth 30Mbit diffserv4 dual-srchost nonat wash no-ack-filter noatm overhead 92
tc qdisc add dev ifb-dl root cake bandwidth 25Mbit diffserv4 dual-dsthost nonat nowash ingress no-ack-filter noatm overhead 92
}
stop()
{
for iface in $ifaces; do
tc qdisc del dev $iface ingress
tc qdisc del dev $iface root
done
tc qdisc del dev wan ingress
tc qdisc del dev wan root
tc qdisc del dev ifb-ul root
tc qdisc del dev ifb-dl root
ip link set ifb-ul down
ip link del ifb-ul
ip link set ifb-dl down
ip link del ifb-dl
}
@Openwrtfunboy I changed the fwmarks as follows:
- fwmark 1 is for all local interface ingress/egress
- fwmark 2 is for all wan ingress/egress associated with OpenWrt traffic
- fwmark 3 is for all VPNs <-- you must set this in LuCi
Really you should take the time to understand what these do so you can test it and adapt for your particular needs.
@moeller0 you may be not so familiar with nftables but does at least the init.d script make sense to you? Now the user can set interface names in nftables variables and init.d script variables and it should generate the appropriate tc calls.
I did not quite understand about the MAC for IoT. I have an IOT network, but it does not have access to the Internet and other VLANs, it is completely isolated, and can only communicate with the Home Assistant controller in another VLAN (made with traffic rules).
Yes then just ignore that / comment those lines out. I used that to set all my IoT devices to bulk because they're just stupid stuff anyway like sending out data relating to my home power usage.
So im right that i should set fwmark 0x1 for all my br-lan.xx and 0x2 for wan and 0x3 for all my vpns?
No just fwmark 0x3 for VPNs in LuCi.
Hm, script will automatically add all corresponding fwmarks?
(i mean 0x1 and 0x2)
Yes - have you read it?
Consider e.g.:
chain hook-output {
type filter hook output priority filter
# OpenWrt->wan
oifname wan mark !=3 mark set 2 goto process-openwrt-to-wan
}
That is, for all packets arriving in the output hook of nftables that does not have a mark of 3 then set the mark to 2 because it is OpenWrt traffic.
I am very happy! Thank you! Very smart! I recently woke up, so I will try everything after the routine. Thanks again, you make my life better
You should test, test and test using:
tcpdump -i ifb-dl -v
And
tcpdump -i ifb-ul -v
You shouldn't see any duplicated packets or encrypted VPN traffic and the DSCPs should get properly handled. A simple test is to ping 9.9.9.9 from a lan client and then run e.g.:
tcpdump -i ifb-ul -v host 9.9.9.9
And also you should see the CAKE diffserv4 counters incrementing properly with:
tc -s qdisc
Any update?
Hello. I'm a little sick and not feeling well, I will definitely do everything in the coming days.
Sorry to hear that. Gesundheit!