Tomando decisões de roteamento com base no UID usando nftables

1

Estou tentando rotear pacotes com base no uid do processo de origem.

Eu sei que o PREROUTING não é atingido pelos pacotes de saída. No iptables, há uma tabela MANGLE onde você pode colocar essas regras dentro da cadeia OUTPUT. nftables não têm um gancho MANGLE ou algo assim. Existe apenas o gancho OUTPUT.

Esta é uma limitação de nftables que não há como marcar pacotes de saída que se originam no host antes da decisão de roteamento?

nftables v0.7 (Scrooge McDuck)
Linux 4.14.5-1-ARCH #1 SMP PREEMPT Sun Dec 10 14:50:30 UTC 2017 x86_64 GNU/Linux
    
por Alexander Theißen 16.12.2017 / 19:11

1 resposta

2

As convenções de nomenclatura em nftables podem ter levado você a pensar que o recurso não existe.

De wiki do nftables ':

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

Netfilter Connmark

Iptables : correspondência do tráfego de saída com o conntrack e o proprietário. Funciona com gotas estranhas

É possível forçar a reflexão fwmark em pacotes de resposta TCP arbitrários?

Pacotes iptables sem uid

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.

    
por 17.12.2017 / 21:58