Rule with XOR does not work as expected

Hi ,

I was playing with the firewall rules, and it looks like there is an issue with the option of XOR of the firewall mark

Basically when a firewall rule is added ( the nft table rule created it has the same logic as rule with assing firewall mark )
Resulting nft rules, one with assing firewall mark, and a second with xor mark

	chain mangle_input {
		type filter hook input priority mangle; policy accept;
		meta l4proto { icmp, ipv6-icmp } iifname "eth0" counter packets 0 bytes 0  meta mark set 0x00000002 comment "!fw4: MARK 02"
		
meta l4proto { icmp, ipv6-icmp } iifname "eth0" meta mark 0x00000001 counter packets 0 bytes 0  meta mark set 0x00000001 comment "!fw4: XOR"
	}


The behavior of the second rule (XOR firewall mark ) is exactly the same as the behavior of the previous rule ( Assing firewall mark )
The expected rule with the XOR mark could be something like this: ( The idea is carry over the already MARK of the packet AND apply the XOR logic )

    chain mangle_input {
            type filter hook input priority mangle; policy accept;
            meta l4proto { icmp, ipv6-icmp } iifname "eth0" counter packets 0 bytes 0  meta mark set 0x00000002 comment "!fw4: MARK 02"
            meta l4proto { icmp, ipv6-icmp } iifname "eth0" counter packets 0 bytes 0  meta mark set meta mark xor 0x00000001 comment "!fw4: XOR_PING"
    }

I'm familiar with the nft tables logic, but not with the ucode which builds/adds the rule itself

Anyone ?

What is the input /etc/config/firewall that generates these rules via ucode?

config zone
	option name 'wan'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'
	option mtu_fix '1'
	list network 'eth0'



config rule
	option name 'MARK 02'
	list proto 'icmp'
	option src 'wan'
	option target 'MARK'
	option set_mark '02'

config rule
	option name 'XOR_PING 01'
	option src 'wan'
	option proto 'icmp'
	option target 'MARK'
	option set_xmark '01'

config rule
	option name 'Allow_ping_mark 03'
	list proto 'icmp'
	option src 'wan'
	option target 'ACCEPT'
	option mark '03'

@jow may know better.
Presented config makes different rules than directed:


        chain input_wan {
           ....
                meta l4proto { "icmp", "ipv6-icmp" } meta mark 0x3 counter accept comment "!fw4: Allow_ping_mark 03"

        chain mangle_input {
                type filter hook input priority mangle; policy accept;
// this totally wrong.
                meta l4proto { "icmp", "ipv6-icmp" } iifname "wan" counter meta mark set 0x1 comment "!fw4: XOR_PING 01"
        }

Make a ticket please, won‘t be able to look into it for some time

1 Like

Thanks for coming back Ill lead the party if needed/able.

@maegrim will you be able to fill issue at https://github.com/openwrt/firewall4/ or should I do it (your repeater fails for me as you describe, obviously)
Summary:
set_mark rule is not emitted at all
set_xmark rule is emitted as if it was set_mark instead

Thanks for the help and double checking!!

I don't have an account to do it "now", but i would like to make the ticket by myself .

OK, give it a try, if you do not make in a week I will do it for you
grep says

root/usr/share/firewall4/templates/mangle-rule.uc:              (rule.set_xmark.mask == 0xFFFFFFFF)
root/usr/share/firewall4/templates/mangle-rule.uc:                      ? fw4.hex(rule.set_xmark.mark)
root/usr/share/firewall4/templates/mangle-rule.uc:                      : (rule.set_xmark.mark == 0)
root/usr/share/firewall4/templates/mangle-rule.uc:                              ? 'mark and ' + fw4.hex(~rule.set_xmark.mask & 0xFFFFFFFF)
root/usr/share/firewall4/templates/mangle-rule.uc:                              : (rule.set_xmark.mark == rule.set_xmark.mask)
root/usr/share/firewall4/templates/mangle-rule.uc:                                      ? 'mark or ' + fw4.hex(rule.set_xmark.mark)
root/usr/share/firewall4/templates/mangle-rule.uc:                                      : (rule.set_xmark.mask == 0)
root/usr/share/firewall4/templates/mangle-rule.uc:                                              ? 'mark xor ' + fw4.hex(rule.set_xmark.mark)
root/usr/share/firewall4/templates/mangle-rule.uc:                                              : 'mark and ' + fw4.hex(~r.set_xmark.mask & 0xFFFFFFFF) + ' xor ' + fw4.hex(r.set_xmark.mark)
root/usr/share/firewall4/templates/rule.uc:             (rule.set_xmark.mask == 0xFFFFFFFF)
root/usr/share/firewall4/templates/rule.uc:                     ? fw4.hex(rule.set_xmark.mark)
root/usr/share/firewall4/templates/rule.uc:                     : (rule.set_xmark.mark == 0)
root/usr/share/firewall4/templates/rule.uc:                             ? `mark and ${fw4.hex(~rule.set_xmark.mask & 0xFFFFFFFF)}`
root/usr/share/firewall4/templates/rule.uc:                             : (rule.set_xmark.mark == rule.set_xmark.mask)
root/usr/share/firewall4/templates/rule.uc:                                     ? `mark or ${fw4.hex(rule.set_xmark.mark)}`
root/usr/share/firewall4/templates/rule.uc:                                     : (rule.set_xmark.mask == 0)
root/usr/share/firewall4/templates/rule.uc:                                             ? `mark xor ${fw4.hex(rule.set_xmark.mark)}`
root/usr/share/firewall4/templates/rule.uc:                                             : `mark and ${fw4.hex(~rule.set_xmark.mask & 0xFFFFFFFF)} xor ${fw4.hex(rule.set_xmark.mark)}`
root/usr/share/ucode/fw4.uc:                    set_xmark: [ "mark", null, NO_INVERT ],
root/usr/share/ucode/fw4.uc:            else if (rule.target == "mark" && !rule.set_mark && !rule.set_xmark) {
root/usr/share/ucode/fw4.uc:                    this.warn_section(data, "must specify option 'set_mark' or 'set_xmark' for target 'mark'");
root/usr/share/ucode/fw4.uc:                            r.set_xmark = {
1 Like

What if you append a mask to your set_xmark?

option set_xmark '0x01/0x00'

I don’t know the correct mask for what you want to do, but without a mask, it assumes the full width and just sets the mark to the xmark value.

fw3 (man 8 iptables-extensions)

-j  MARK
--set-xmark value[/mask]
      Zeroes out the bits given by mask and XORs value into the packet mark ("nfmark"). If mask is omitted, 0xFFFFFFFF is assumed
--set-mark value[/mask]
      Zeroes out the bits given by mask and ORs value into  the packet mark. If mask is omitted, 0xFFFFFFFF is assumed.

complemeņtary inf

https://git.netfilter.org/iptables/tree/extensions/libxt_MARK.txlate

Yes, using the XOR in that way the results are as expected.

option set_xmark 01/00

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.