¿Manera simple de crear un túnel de un puerto local a otro?


76

Tengo un servidor de desarrollo, al que solo se puede acceder desde 127.0.0.1:8000, no desde 192.168.1.x: 8000. Como truco rápido, ¿hay alguna manera de configurar algo para escuchar en otro puerto (por ejemplo, 8001) para que desde la red local pueda conectar 192.168.1.x: 8001 y así se canalice el tráfico entre el cliente y 127.0 .0.1: 8000?


44
Netcat puede hacer esto.
Andy

Respuestas:


44

Usar ssh es la solución más fácil.

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

Esto reenvía el puerto local 8001 en su estación de trabajo a la dirección localhost en el puerto remote-server.com 8000.
-gsignifica permitir que otros clientes en mi red se conecten al puerto 8001 en mi estación de trabajo. De lo contrario, solo los clientes locales en su estación de trabajo pueden conectarse al puerto reenviado.
-Nsignifica que todo lo que estoy haciendo es reenviar puertos, no iniciar un shell.
-fsignifica bifurcación en segundo plano después de una conexión SSH exitosa e inicio de sesión.
El puerto 8001 permanecerá abierto para muchas conexiones, hasta que ssh muera o muera. Si estás en Windows, el excelente cliente SSH PuTTY también puede hacer esto. Use 8001 como el puerto local y localhost: 8000 y el destino y agregue un reenvío de puerto local en la configuración. Puede agregarlo después de una conexión exitosa con PuTTY.


44
¿Qué hace el user@remote-server.com? Definitivamente no es necesario para el reenvío de puertos, sin embargo, ssh exige tener este argumento, más aún, intenta conectarse allí. Y al configurar esta molesta opción para hostname, se genera …port 22: Connection refused (no, no utilicé el puerto 22) . A menos que me falte algo, el comando simplemente no funciona.
Hola Ángel

@ Hi-Angel user@remote-server.comes solo un ejemplo y no debes tomarlo literalmente. Debe reemplazar esto con el nombre de la computadora a la que desea conectarse y su nombre de usuario en esta computadora. Esta información es necesaria para establecer una conexión ssh. Solo después de que se establece la conexión ssh, los puertos se pueden reenviar a través de esta conexión.
Piotr Dobrogost

Si desea que el puerto esté disponible desde el arranque, consulte "autossh" en un servicio systemd utilizando el método anterior - everythingcli.org/ssh-tunnelling-for-fun-and-profit-autossh
Richard Hollis

También recibo "conexión rechazada". Y todavía no entiendo por qué se necesita el argumento user@remote-server.com cuando no hay una conexión SSH involucrada (de acuerdo con -N). Debería reenviar paquetes.
Alexander Taylor

2
@AlexanderTaylor -Nno significa que no haya conexión SSH. Simplemente significa do not execute a remote command(ver la página del manual ). El <user>@<host>argumento es necesario, porque esto hace abrir una conexión SSH a <host>(que para el caso de OP sería localhost), y reenvía el puerto deseado a través de ese túnel SSH. Es una solución para el problema de OP, pero no la más simple. Para reenviar a localhost sin usar ssh, puede usar socato netcatcomo en StephaneChazelas y las respuestas de un usuario no

94

Con socaten el servidor:

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

De forma predeterminada, socatescuchará en el puerto TCP 8001 en cualquier dirección IPv4 o IPv6 (si es compatible) en la máquina. Puede restringirlo a IPv4 / 6 reemplazando tcp-listencon tcp4-listeno tcp6-listen, o a una dirección local específica agregando un ,bind=that-address.

Lo mismo para el zócalo de conexión al que está enviando proxy, puede usar cualquier dirección en lugar de localhost, y reemplazar tcpcon tcp4o tcp6si desea restringir la resolución de la dirección a direcciones IPv4 o IPv6.

Tenga en cuenta que para el servidor que escucha en el puerto 8000, la conexión aparecerá como proveniente del proxy (en el caso de localhostque así sea localhost), no del cliente original. Debería usar enfoques DNAT (pero que requieren privilegios de superusuario) para que el servidor pueda saber quién es el cliente.


1
Gracias, esto es genial ya que no es necesario que tenga un servidor ssh local en ejecución.
jontro

¿Puedo usar el mismo puerto pero diferente dirección?
Amós

@amos, ver editar.
Stéphane Chazelas

¿También sería posible reenviar tráfico solo desde IP específicas?
Phate

1
@Phate, consulte Dile a socat que escuche las conexiones desde una única dirección IP (y las opciones rangey tcpwrapen la socatpágina de manual).
Stéphane Chazelas

46

Usar lo tradicional nces la solución más fácil:

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

Esta versión de ncestá en el netcat-traditionalpaquete en Ubuntu. (Tienes que hacerlo update-alternativeso llamarlo nc.traditional).

Tenga en cuenta que, a diferencia de ssh, esto no está cifrado. Tenga esto en cuenta si lo usa fuera de un host.


2
Alguien sabe el equivalente en netcat-openbsd?
Sridhar Sarnobat

2
Analógico para netcatla versión que se incluye en busybox: nc -v -lk -p 8001 -e /usr/bin/nc 127.0.0.1 8000. ( Descripción de los parámetros )
Ivan Kolmychek

2
Funciona, pero el nccomando termina después de la primera conexión remota. Agregue -ksi necesita mantenerlo funcionando.
Sopalajo de Arrierez

Recibo este error: nc: cannot use -p and -len CentOS 6.4. ¿Hay alguna solución?
Nick Predey

Prefiero esta solución sobre la ssh porque hace que sea más fácil de usar como root, cuando uno necesita reenviar localmente un puerto privilegiado.
Christian

24

OpenBSD netcat está disponible por defecto en Linux y también en 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

Una alternativa que funciona en OS X bash es usar una tubería bidireccional . Puede funcionar en otros Unixes:

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

Al principio no me di cuenta de que estabas usando openbsd netcat. Esto es mejor que tener que instalar otro netcat desde un paquete de Ubuntu.
RobertR

El ejemplo de OpenBSD falló en Ubuntu 15.04. Con los redireccionamientos de shell, netcat no puede abrir el puerto para escuchar como lo ve ss -tano netstat -tan.
Justin C

⁺¹. FTR: la forma alternativa funciona en Ubuntu
Hi-Angel

No entiendo tu solución. ¿Puedes explicarlo?
Trismegistos

@trismegistos En estos ejemplos, el oyente netcat y el cliente redirigen la entrada a algunos archivos compartidos (mkfifo pipes..primero en el primero en salir), y usan esos archivos compartidos como su fuente / destino de entrada / salida, creando efectivamente un túnel. Por lo general, se usan cliente / escucha, pero algunas técnicas usan cliente + cliente / escucha + escucha- wiki.securityweekly.com/… y slideshare.net/amiable_indian/secrets-of-top-pentesters son lecturas obligatorias.
Info5ek

4

Citando la respuesta de David Spillett en ServerFault

rinetd debería hacer el trabajo, y se puede obtener un binario de Windows para ello en http://www.boutell.com/rinetd/ (para cualquiera que busque lo mismo en Linux, rinetd está en los repositorios estándar de casi todas las distribuciones entonces se puede instalar con "apt-get install rinetd" o "yum install rinetd" o similar)

Es un binario simple que toma un archivo de configuración en el formato

bindaddress bindport connectaddress connectport

Por ejemplo:

192.168.1.1 8001 127.0.0.1 8000

o

0.0.0.0 8001 127.0.0.1 8000

si desea vincular el puerto entrante a todas las interfaces.


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

service iptables save
service iptables restart

Al intentar conectarme dport, como en nc -v localhost 2345, me estoy poniendo Connection refused. No soy muy bueno en iptables, pero supongo que el dport debe tener una aplicación de escucha.
Hola Ángel

¿Qué sucede si el puerto de origen está en una interfaz diferente que el puerto de destino?
Trismegistos

0

Según la respuesta de Mark A. , tuve que hacer un pequeño ajuste para que funcione en mi Mac (al menos en macOS Mojave Versión 10.14.4)

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

Esa declaración printf parece ser crucial. De lo contrario, el comando netcat para conectarse al puerto 8000 nunca intentará conectarse realmente, y el comando netcat para escuchar en el puerto 8001 nunca escuchará en el puerto 8001. Sin el printf, cada vez que intentara conectarme al puerto 8001 obtendría conexión denegada.

Mi suposición es que netcat debe bloquear de alguna manera en stdin (tal vez esté tratando de leerlo por alguna razón) antes de realizar cualquier operación de Socket. Como tal, sin la declaración printf escrita en fifo a, el comando netcat nunca comenzará a escucharse en el puerto 8001.

Nota: Hubiera dejado una respuesta en la publicación de Mark, pero aún no tengo reputación.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.