Thanks for the detailed explanations Máté and Bazsi. They answered a lot of questions I had. I do have a couple of follow up questions if you don’t mind: > The device in your advanced routing rule "ip route add local default dev lo table 100" is not really used for input purposes. >From my test, without "meta mark set 1” being after the tproxy rule, and thus bypassing the previous routing rule, a packet arriving on lan lands on no chain after it goes through the filter prerouting chain. I assume it gets dropped during the routing decision? With "meta mark set 1”, after going through the filter prerouting chain, it shows up in the mangle input chain. Maybe I missed something, but it seems "tproxy to 127.0.0.1:1234" is not enough to have a packet redirected to a local socket? My test belongs to the “open dynamically” case you mentioned. I wonder if it's due to the conflict between tproxy asking the packet to be redirected to 127.0.0.1:1234, and the ip stack's refusal of treating the destination as local without the routing rule? > iifname is not changed by the tproxy rule and the packet content is not overwritten either. This makes sense. I'm curious about how tproxy works because I want to differentiate between packets that intrinsically go through the input chain (which should be rejected) and those go through it because of the tproxy rule (which should be accepted). I initially thought I could just reject any packet go through the filter input chain with iifname being “lo”. But if it’s not changed, what would be a good way to differentiate? I did found out that with "meta mark set 1”, the mark was still set in the mangle input chain, but it got cleared in the next filter input chain. So I guess it’s a dead end. > It does not need to be in the nat table, in the iptables times we put it in mangle IIRC. I did use mangle in my real device, but mistakingly typed nat here, sorry about the confusion. Regards, Glen