Maneira simples de criar um túnel de uma porta local para outra?


76

Eu tenho um servidor de desenvolvimento, que só é acessível a partir de 127.0.0.1:8000, não 192.168.1.x: 8000. Como um hack rápido, existe uma maneira de configurar algo para escutar em outra porta (por exemplo, 8001) para que, a partir da rede local, eu possa conectar 192.168.1.x: 8001 e encapsular o tráfego entre o cliente e o 127.0 .0.1: 8000?


4
O netcat pode fazer isso.
Andy

Respostas:


44

Usar ssh é a solução mais fácil.

ssh -g -L 8001: localhost: 8000 -f -N user@remote-server.com

Isso encaminha a porta local 8001 em sua estação de trabalho para o endereço localhost na remote-server.com porta 8000.
-gsignifica permitir que outros clientes na minha rede se conectem à porta 8001 na minha estação de trabalho. Caso contrário, apenas clientes locais em sua estação de trabalho poderão se conectar à porta encaminhada.
-Nsignifica que tudo o que estou fazendo é encaminhar portas, não inicie um shell.
-fsignifica entrar em segundo plano depois de uma conexão e login SSH bem-sucedidos.
A porta 8001 permanecerá aberta para muitas conexões, até que o ssh morra ou seja morto. Se você estiver no Windows, o excelente cliente SSH PuTTY também poderá fazer isso. Use 8001 como a porta local e localhost: 8000 e o destino e adicione um encaminhamento de porta local nas configurações. Você pode adicioná-lo após uma conexão bem-sucedida com o PuTTY.


4
O que user@remote-server.comfaz? Definitivamente, não é necessário o encaminhamento de porta, no entanto, o ssh exige que esse argumento, mais ainda, tente se conectar a ele. E ao definir essa opção traquina para nome de host que ela gera …port 22: Connection refused (não, eu não usei a porta 22) . A menos que esteja faltando alguma coisa, o comando claramente não funciona.
Hi-Angel

@ Hi-Angel user@remote-server.comé apenas um exemplo e você não deve interpretar isso literalmente. É necessário substituí-lo por um nome de computador ao qual você deseja se conectar e seu nome de usuário neste computador. Esta informação é necessária para estabelecer a conexão ssh. Somente após o estabelecimento da conexão ssh, as portas podem ser encaminhadas por essa conexão.
Piotr Dobrogost

Se você quer a porta para estar disponível a partir de inicialização, em seguida, ver "autossh" em um serviço systemd usando o método acima - everythingcli.org/ssh-tunnelling-for-fun-and-profit-autossh
Richard Hollis

Eu também recebo "conexão recusada". E ainda não entendo por que o argumento user@remote-server.com é necessário quando não há conexão SSH envolvida (de acordo com -N). Deve apenas encaminhar pacotes.
Alexander Taylor

2
@AlexanderTaylor -Nnão significa que não há conexão SSH. Simplesmente significa do not execute a remote command(veja a página de manual ). O <user>@<host>argumento é necessário, porque este faz abrir uma conexão SSH para <host>(o que para o caso de OP seria localhost), e encaminha a porta desejada através desse túnel SSH. É uma solução para o problema do OP, mas não a mais simples. Para encaminhar para localhost sem o uso de ssh, você pode usar socatou netcatcomo em StephaneChazelas e 's not-a-user respostas

94

Com socatno servidor:

socat tcp-listen:8001,reuseaddr,fork tcp:localhost:8000

Por padrão, socatescutará na porta TCP 8001 em qualquer endereço IPv4 ou IPv6 (se suportado) na máquina. Você pode restringi-lo ao IPv4 / 6 substituindo tcp-listenpor tcp4-listenou tcp6-listenou para um endereço local específico adicionando a ,bind=that-address.

O mesmo para o soquete de conexão ao qual você está executando o proxy, você pode usar qualquer endereço no lugar de localhoste substituir tcppor tcp4ou tcp6se desejar restringir a resolução do endereço aos endereços IPv4 ou IPv6.

Note-se que para o servidor escuta na porta 8000, a conexão aparecerá como provenientes do proxy (no caso de localhost, que será localhost), e não o cliente original. Você precisaria usar abordagens DNAT (mas que requerem privilégios de superusuário) para que o servidor possa saber quem é o cliente.


1
Obrigado, isso é ótimo, pois você não precisa ter um servidor ssh local em execução.
jontro

Posso usar a mesma porta, mas com endereço diferente?
Amos

@amos, veja editar.
Stéphane Chazelas

Também seria possível encaminhar tráfego apenas de IPs específicos?
Phate 23/08/19

1
@Phate, consulte Diga ao socat para ouvir conexões de um único endereço IP (e as opções rangee tcpwrapna socatpágina de manual).
Stéphane Chazelas

46

Usar o tradicional ncé a solução mais fácil:

nc -l -p 8001 -c "nc 127.0.0.1 8000"

Esta versão do ncestá no netcat-traditionalpacote no Ubuntu. (Você precisa update-alternativesou chama nc.traditional.)

Observe que, ao contrário do ssh, isso não é criptografado. Lembre-se disso se você o usar fora de um host.


2
alguém sabe o equivalente netcat-openbsd?
Sridhar Sarnobat

2
Analógica para netcata versão que está incluído no busybox: nc -v -lk -p 8001 -e /usr/bin/nc 127.0.0.1 8000. ( Descrição dos parâmetros )
Ivan Kolmychek 16/03

2
Funcionando, mas o nccomando termina após a primeira conexão remota. Adicione -kse você precisar mantê-lo em execução.
Sopalajo de Arrierez

Estou recebendo este erro: nc: cannot use -p and -lno CentOS 6.4. Existe uma solução alternativa?
9116 Nick Predey

Prefiro essa solução à ssh porque facilita o uso como root, quando é necessário encaminhar localmente uma porta privilegiada.
Christian

24

O OpenBSD netcat está disponível por padrão no Linux e também no OS X.

OSX:

mkfifo a
mkfifo b
nc 127.0.0.1 8000 < b > a &
nc -l 8001 < a > b &

Linux:

mkfifo backpipe
nc -l 12345 0<backpipe | nc www.google.com 80 1>backpipe

Uma alternativa que funciona no bash do OS X é usar um tubo bidirecional . Pode funcionar em outros Unixes:

nc 127.0.0.1 8000 <&1 | nc -l 8001 >&0

Eu não percebi no começo que você estava usando o openbsd netcat. Isso é melhor do que ter que instalar outro netcat a partir de um pacote Ubuntu.
RobertR

O exemplo do OpenBSD falhou no Ubuntu 15.04. Com os redirecionamentos de shell, o netcat falha ao abrir a porta para escuta, conforme visto por ss -tanou netstat -tan.
Justin C

⁺¹ FTR: a maneira alternativa funciona no Ubuntu
Hi-Angel

Eu não entendo sua solução. Você pode explicar isso?
Trismegistos

@trismegistos Nestes exemplos, o ouvinte e o cliente netcat redirecionam a entrada para alguns arquivos compartilhados (mkfifo pipes .. primeiro a sair) e usam esses arquivos compartilhados como sua origem / destino de entrada / saída, criando efetivamente um túnel. Normalmente, cliente / ouvinte são usados, mas algumas técnicas usam cliente + cliente / ouvinte + ouvinte- wiki.securityweekly.com/… e slideshare.net/amiable_indian/secrets-of-top-pentesters são leituras obrigatórias.
Info5ek

4

Citando um David Spillett 's resposta em ServerFault

O rinetd deve fazer o trabalho, e um binário do Windows pode ser obtido em http://www.boutell.com/rinetd/ (para quem procura a mesma coisa no Linux, o rinetd está nos repositórios padrão de praticamente todas as distribuições pode ser instalado com "apt-get install rinetd" ou "yum install rinetd" ou similar)

É um binário simples que pega um arquivo de configuração no formato

bindaddress bindport connectaddress connectport

Por exemplo:

192.168.1.1 8001 127.0.0.1 8000

ou

0.0.0.0 8001 127.0.0.1 8000

se você deseja vincular a porta de entrada a todas as interfaces.


3
iptables -t nat -A PREROUTING -p tcp --dport <origin-port> -j REDIRECT --to-port <destination-port>

service iptables save
service iptables restart

Ao tentar me conectar dport, como nc -v localhost 2345estou recebendo Connection refused. Eu não sou muito bom em iptables, mas acho que o dport precisa ter um aplicativo de escuta.
Hi-Angel

E se a porta de origem estiver em uma interface diferente da porta de destino?
Trismegistos

0

Com base na resposta de Mark A. , tive que fazer um pequeno ajuste para que ele funcionasse no meu Mac (pelo menos no macOS Mojave versão 10.14.4)

mkfifo a
mkfifo b
nc 127.0.0.1 8000 < b > a &
nc -l 8001 < a > b &
printf "" > a

Essa declaração printf parece ser crucial. Caso contrário, o comando netcat para conectar-se à porta 8000 nunca tentará realmente se conectar, e o comando netcat para escutar na porta 8001 nunca escutará na porta 8001. Sem o printf, sempre que eu tentasse conectar-me à porta 8001, obteria Ligação recusada.

Minha suposição é que o netcat deve de alguma forma bloquear o stdin (talvez esteja tentando lê-lo por algum motivo) antes de realmente executar qualquer operação do soquete. Como tal, sem a instrução printf escrevendo para fifo a, o comando netcat nunca começará a escutar na porta 8001.

Nota: eu teria deixado uma resposta na postagem de Mark, mas ainda não tenho reputação.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.