As convenções de nomenclatura em nftables podem ter levado você a pensar que o recurso não existe.
route, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with iptables, this chain type provides equivalent semantics to the mangle table but only for the output hook (for other hooks use type filter instead). This is supported by the ip and ip6 table families.
Então, fazendo tudo isso a partir de um contêiner LXC, usando o kernel 4.9.0-4-amd64 #1 SMP Debian 4.9.65-3 (2017-12-03)
do debian stretch, eu tornarei o uid 1001 o único usuário capaz de se conectar à internet (aqui DNS público do Google usando TCP):
# ip route default via 10.0.3.1 dev eth0 10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.66 # pkill -9 dhclient # ip route del default # ip route add default via 10.0.3.2 dev eth0 # 10.0.3.2 doesn't exist, but a default route is required for the routing code to trigger the fwmark rule at all, else there's a direct "Network is unreachable" with no packet generated. # ip route add default via 10.0.3.1 table 10 # ip rule add fwmark 1 table 10
A nomenclatura canônica para mangle abaixo pode ser encontrada aqui (ou / usr / share / doc ...). -150 é o valor de NF_IP_PRI_MANGLE
# nft add table ip mangle # nft 'add chain ip mangle output { type route hook output priority -150; }' # nft add rule ip mangle output skuid 1001 counter mark set 1 # id uid=0(root) gid=0(root) groups=0(root) # nc -v -n -z 8.8.8.8 53 # will timeout on ARP request to 10.0.3.2 nc: connect to 8.8.8.8 port 53 (tcp) failed: No route to host # su - test $ id uid=1001(test) gid=1001(test) groupes=1001(test) $ nc -v -n -z 8.8.8.8 53 Connection to 8.8.8.8 53 port [tcp/*] succeeded!
Última nota. Há um comentário sobre o uso de um namespace de rede para simplificar a configuração, e só posso concordar: teria sido mais difícil dar este exemplo sem um contêiner (com seu próprio namespace de rede). Além disso, por exemplo, se houver um comando suid root usando a rede, dependendo de como o comando está funcionando, ele pode acionar ou não a marca e a rota.
UPDATE: alguns pacotes iniciados pela conexão do usuário não pertencem mais ao usuário. Isso pode acontecer para o último ACK
que reconhece um pacote FIN
no final de uma conexão, e muitas vezes é o caso de RST
pacotes quando uma conexão é abortada prematuramente. Esses pacotes não corresponderão a um proprietário, portanto, não receberão uma marca, não serão reencaminhados e isso poderá levar a tempos limite no final de uma transferência. Para evitar isso, isso deve ser combinado com outros recursos, como ct mark set mark
/ mark set ct mark
(equivalente a iptables
' CONNMARK
). Mais informações sobre marcas conntrack e problemas e soluções equivalentes do iptables:
marca nftables e marca conntrack
É possível forçar a reflexão fwmark em pacotes de resposta TCP arbitrários?
Os tempos limite ocorreram no teste anterior "com êxito" com nc
acima, mas, como o comando retornou, ele não era visível sem a captura da rede. Os tempos limite ocorreram no lado do servidor ponto a ponto. Para resolvê-lo, mantenha os mesmos comandos de roteamento, mas substitua as regras do nft acima por:
# nft add table ip mangle
# nft 'add chain ip mangle output { type route hook output priority -150; }'
# nft flush chain ip mangle output
# nft add rule ip mangle output mark set ct mark counter
# nft add rule ip mangle output mark ne 0 counter accept
# nft add rule ip mangle output skuid 1001 counter mark set 1
# nft add rule ip mangle output ct mark set mark counter
Os counter
s são apenas para depuração.