Por que uma regra de porta de origem quebra um dos seus caminhos SSH
Uma correspondência «sport 22» não diz a qual entrada SSH uma resposta pertence. Limite a regra de política ao fluxo de gestão em vez de uma tabela apenas para WAN.
Duas entradas de gestão num único host, uma única porta de serviço e uma regra de política que devia ajudar ambas. A regra corresponde à porta de origem 22, envia a pesquisa para uma tabela que só conhece o valor predefinido da WAN, e a entrada VPN deixa de responder a novos inícios de sessão enquanto a entrada direta continua a funcionar. Nada disso é misterioso quando o seletor é lido corretamente. Uma porta de origem identifica um serviço, não o caminho por onde chegou uma ligação.
Duas entradas, uma única porta de serviço
O host tem um endereço do lado da LAN e um endereço VPN, e o sshd escuta em ambos. Por isso, uma sessão direta e uma sessão em túnel partilham a porta de serviço e diferem apenas em qual endereço local recebe a ligação.
Essa diferença basta para escolher um caminho de resposta, e é exatamente a diferença que uma regra baseada na porta descarta. Ambas as sessões produzem respostas cuja porta de origem é 22, por isso uma regra que corresponda a essa porta não as consegue separar. Envia ambas as pesquisas para a mesma tabela, e uma delas recebe uma resposta que não encaixa. A correção é fazer corresponder o atributo que realmente difere.
Dar a cada entrada a sua própria porta também funcionaria, e tratar isso como um requisito é uma escolha de projeto, não uma propriedade do SSH.
Leia a regra, depois a tabela
Uma regra de política é um seletor ordenado, e a primeira que devolve uma resposta utilizável termina a pesquisa. Leia a lista por ordem e repare em qual regra pode ganhar.
Depois leia a tabela para a qual essa regra aponta, porque uma regra que se resolve com sucesso não é uma regra que se resolve de forma útil. Uma tabela que contém apenas uma rota predefinida envia a resposta com origem VPN para fora pela interface WAN. Uma rota mais específica numa tabela posterior nunca é consultada, e é por isso que acrescentar uma segunda tabela tantas vezes não muda nada. A tabela selecionada é o que deve ser inspecionado.
ip -4 rule show
ip route show table 100
ip route show table main
Estas duas saídas juntas explicam o resultado; qualquer uma delas isolada convida a uma conclusão errada.
Limite a regra ao fluxo que pretende
O atributo que separa as duas entradas é o endereço de origem local. Uma regra que corresponde a esse endereço envia apenas as sessões em túnel para a tabela privada e deixa as sessões diretas na tabela principal.
Essa regra tem de ser emparelhada com uma tabela que contenha a rota privada e o caminho de regresso para essa sub-rede. Limite ambas ao tráfego de gestão em vez de a cada serviço do host. Uma regra que captura todo o tráfego desse endereço também reencaminhará tudo o resto que o host envie a partir dele. O estreito vence o engenhoso aqui, porque a pessoa seguinte tem de o ler.
sudo ip rule add from 10.90.0.1 lookup 100 priority 100
sudo ip route add 10.90.0.0/24 dev wg0 table 100
ip route get 10.90.5.20 from 10.90.0.1
Se ambas as entradas forem traduzidas para um único endereço local, essa distinção desaparece e o projeto precisa de estado consciente da ligação em vez disso.
Mantenha o ouvinte, a permissão e a seleção da resposta separados
Três coisas distintas têm de ser verdadeiras para que uma sessão funcione: o endereço existe, o serviço escuta nele e a resposta encontra o caminho de volta. Uma alteração de rota corrige apenas a terceira.
A configuração do ouvinte é um ficheiro próprio e um recarregamento próprio, e vários endereços de escuta são normais. A autenticação é novamente uma terceira decisão, e uma exceção de encaminhamento não dá acesso a ninguém. Mantenha a verificação da chave do host, a autenticação da conta e as restrições de origem nas duas entradas, e resista à tentação de enfraquecer os outros controlos do túnel para que um único caminho de gestão funcione.
Mantenha um canal de recuperação que não dependa do caminho que está a alterar, porque um erro aqui bloqueia a própria correção.
Prove-o com uma sessão nova, não com uma antiga
Um terminal estabelecido não prova nada, pois foi admitido antes da alteração. Abra uma sessão nova através de cada entrada prevista.
ss -ltnp | grep ':22'
sudo sshd -T | grep -i listenaddress
ssh -v [email protected] true
sudo journalctl -u ssh -n 30
Depois repita a reconexão da VPN e tente novamente, porque uma rota que sobrevive a uma reconexão não é o mesmo que uma acrescentada a uma tabela que a reconexão esvazia. Observe as origens negadas separadamente das permitidas, para que uma tentativa bloqueada não se esconda atrás de uma sessão a funcionar. Guarde o endereço local, a regra e a tabela junto ao resultado. Se, em vez disso, dividir as portas, registe isso como uma decisão operacional e não como um limite do SSH.