My problem is that when I print out the socket information using getsockname and getpeername, the source address is always the server's. If I connect to the server directly through a port that is not affected by the iptables rule I see the client address as expected. Why is port forwarding affecting the source address?
Vou explicar, mas esteja avisado de que esta será uma longa explicação .
Vamos primeiro entender o que é uma Conexão TCP : É um intercâmbio de dados orientado à conexão entre uma 'tupla iniciadora' (IP,Port)
e uma 'tueta terminadora' (IP,port)
.
Em outras palavras, a conexão TCP é definida por um quatro-ple de (Client_IP,Client_Port,Server_IP,Server_Port)
.
Isso significa que toda a transferência de informações para essa conexão TCP precisa atender a quatro definições.
Agora, vamos supor que seu servidor esteja localizado em 1.1.1.1 e o cliente em 2.2.2.2. O cliente abre a conexão com a porta 80 do seu servidor. Assumindo que a porta efêmera do cliente é 34567, temos o quatro-pto (2.2.2.2,34567,1.1.1.1,80).
No seu servidor, o pacote é redirecionado para 1.1.1.1:10080. Mas isso resulta em um diferente número de conexões! Por exemplo, (2.2.2.2,34567,1.1.1.1,18080).
O que o ouvinte real fará? Por que responderia diretamente ao 2.2.2.2:34567, resultando no pacote a ser descartado pelo cliente, pois o cliente possui o múltiplo de (2.2.2.2.34567,1.1.1.1,80) e não (2.2. 2.2.34567,1.1.1.1,18080).
Portanto, nesse caso, o REDIRECT
alvo precisa criar um mapeamento temporário de quatro páginas:
(2.2.2.2,34567,1.1.1.1,80) --> (1.1.1.1,x,1.1.1.1,10080)
(x é uma porta temporária e efêmera para permitir que a conexão TCP seja construída).
Com esse mapeamento temporário, o servidor em 10080 responde a netfilter
e ocorre um mapeamento reverso:
(1.1.1.1,x,1.1.1.1,10080) --> (2.2.2.2,34567,1.1.1.1,80)
netfilter
envia o pacote que foi mapeado para o cliente, e está tudo bem.
Portanto, se você precisar saber o endereço IP do cliente, NÃO poderá usar o REDIRECT
target. Em vez disso, coloque seu servidor real em uma sub-rede diferente e use DNAT
target, com seu servidor Linux atuando como um roteador completo. Supondo que seu servidor real tenha um endereço de LAN local de 192.168.1.51, o mapeamento será:
(2.2.2.2,34567,1.1.1.1,80) --> (2.2.2.2,34567,192.168.1.51,80)
O servidor em 192.168.1.51 responderá ao 2.2.2.2, e o roteador irá inverter o mapa:
(2.2.2.2,34567,192.168.1.51,80) --> (2.2.2.2,34567,1.1.1.1,80)
E tudo bem.