I have a development server, which is only accessible from, not 192.168.1.x:8000. As a quick hack, is there a way to set up something to listen on another port (say, 8001) so that from the local network I could connect 192.168.1.x:8001 and it would tunnel the traffic between the client and

  • 4
    netcat can do this.
    – Andy
    Commented Apr 1, 2011 at 5:25
  • Is there anything that can be run on an Android device? Or a limitation of Android that prevents such a solution? Commented Oct 12, 2020 at 1:35

8 Answers 8


With socat on the server:

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

By default, socat will listen on TCP port 8001 on any IPv4 or IPv6 address (if supported) on the machine. You can restrict it to IPv4/6 by replacing tcp-listen with tcp4-listen or tcp6-listen, or to a specific local address by adding a ,bind=that-address.

Same for the connecting socket you're proxying to, you can use any address in place of localhost, and replace tcp with tcp4 or tcp6 if you want to restrict the address resolution to IPv4 or IPv6 addresses.

Note that for the server listening on port 8000, the connection will appear as coming from the proxy (in the case of localhost, that will be localhost), not the original client. You'd need to use DNAT approaches (but which requires superuser privileges) for the server to be able to tell who's the client.

  • 4
    Thanks, this is great since you do not have to have a local ssh server running.
    – jontro
    Commented Dec 15, 2015 at 15:11
  • Can I use the same port but different address?
    – Amos
    Commented Feb 14, 2017 at 4:35
  • @amos, see edit. Commented Feb 14, 2017 at 18:23
  • 2
    @Phate, see Tell socat to listen to connections from a single IP address (and the range and tcpwrap options in the socat man page). Commented Aug 23, 2018 at 18:38
  • 3
    this solution better than nc.traditional solution below, this one didn't disconnect after a few connections
    – Kokizzu
    Commented Jan 29, 2020 at 6:50

Using ssh is the easiest solution.

ssh -g -L 8001:localhost:8000 -f -N [email protected]

This forwards the local port 8001 on your workstation to the localhost address on remote-server.com port 8000.
-g means allow other clients on my network to connect to port 8001 on my workstation. Otherwise only local clients on your workstation can connect to the forwarded port.
-N means all I am doing is forwarding ports, don't start a shell.
-f means fork into background after a successful SSH connection and log-in.
Port 8001 will stay open for many connections, until ssh dies or is killed. If you happen to be on Windows, the excellent SSH client PuTTY can do this as well. Use 8001 as the local port and localhost:8000 and the destination and add a local port forwarding in settings. You can add it after a successful connect with PuTTY.

  • 5
    What does the [email protected] do? It's definitely unneeded for port forwarding, however ssh mandates having this argument, more over, it tries to connect there. And upon setting this pesky option to hostname it outputs …port 22: Connection refused (no, I didn't use the 22 port). Unless I'm missing something, the command plainly doesn't work.
    – Hi-Angel
    Commented Dec 1, 2016 at 13:43
  • @Hi-Angel [email protected] is just an example and you should not take it literally. You have to replace this with a name of computer you want to connect to and your username on this computer. This information is needed to establish ssh connection. Only after ssh connection is established ports can be forwarded through this connection. Commented Feb 1, 2017 at 23:45
  • If you want the port to be available from boot then see "autossh" in a systemd service using the above method - everythingcli.org/ssh-tunnelling-for-fun-and-profit-autossh Commented Oct 27, 2017 at 13:03
  • I also get "connection refused". And I still don't understand why the [email protected] argument is needed when there is no SSH connection involved (according to -N). Should just forward packets. Commented Dec 10, 2017 at 7:42
  • 6
    @AlexanderTaylor -N does not mean there is no SSH connection. It simply means do not execute a remote command (see the man page). The <user>@<host> argument is necessary, because this does open an SSH connection to <host> (which for OP's case would be localhost), and forwards the desired port through that SSH tunnel. It is one solution for OP's problem, but not the simplest. To forward to localhost without using ssh, you can use socat or netcat as in StephaneChazelas and not-a-user 's answers
    – user143943
    Commented Apr 18, 2018 at 11:35

Using the traditional nc is the easiest solution:

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

This version of nc is in the netcat-traditional package on Ubuntu. (You have to update-alternatives or call it nc.traditional.)

Note that in contrast to ssh this is not encrypted. Keep that in mind if you use it outside one host.

  • 5
    anyone know the equivalent on netcat-openbsd? Commented Jul 23, 2017 at 18:20
  • 7
    Analog for netcat version that is included in busybox: nc -v -lk -p 8001 -e /usr/bin/nc 8000. (Description of params) Commented Mar 16, 2018 at 13:30
  • 3
    Working, but the nc command ends after the first remote connection. Add -k if you need to keep it running. Commented Jun 20, 2018 at 23:49
  • 4
    I'm getting this error: nc: cannot use -p and -l on CentOS 6.4. Is there a work around?
    – Nick
    Commented Jul 16, 2018 at 15:52
  • I prefer this solution over the ssh one because it makes it easier to use as root, when one needs to locally forward a privileged port.
    – Christian
    Commented Aug 15, 2018 at 0:58

OpenBSD netcat is available by default on Linux and also on OS X.


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


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

An alternative that works on OS X bash is to use a bidirectional pipe. It may work on other Unixes:

nc 8000 <&1 | nc -l 8001 >&0
  • I didn't notice at first that you were using openbsd netcat. This is better than having to install another netcat from an Ubuntu package.
    – RobertR
    Commented Feb 26, 2015 at 15:24
  • OpenBSD example failed on Ubuntu 15.04. With the shell redirects, netcat fails to open the port for listening as seen by ss -tan or netstat -tan.
    – Justin C
    Commented Sep 3, 2015 at 0:12
  • ⁺¹. FTR: the alternative way works on Ubuntu
    – Hi-Angel
    Commented Nov 30, 2016 at 10:41
  • I don't understand your solution. Can you explain it? Commented Sep 19, 2017 at 8:21
  • @trismegistos In these examples the netcat listener and client redirect input into some shared files (mkfifo pipes..first in first out), and use those shared files as their source/destination of input/output, effectively creating a tunnel. Usually client/listener are used, but some techniques use client+client/listener+listener- wiki.securityweekly.com/… and slideshare.net/amiable_indian/secrets-of-top-pentesters are must reads.
    – Info5ek
    Commented Oct 4, 2017 at 18:02

Quoting a David Spillett's answer on ServerFault, replacing the missing link with a working repo:

rinetd should do the job, and a Windows binary for it can be had from https://github.com/samhocevar/rinetd (for anyone looking for the same thing under Linux, rinetd is in the standard repositories of just about every distro so can be installed with "apt-get install rinetd" or "yum install rinetd" or similar)

It is a simple binary that takes a configuration file in the format

bindaddress bindport connectaddress connectport

For example: 8001 8000

or 8001 8000

if you want to bind the incoming port to all the interfaces.

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

service iptables save
service iptables restart
  • Upon trying to connect to dport, as in nc -v localhost 2345, I'm getting Connection refused. I'm not very good in iptables, but I guess the dport has to have a listening app.
    – Hi-Angel
    Commented Dec 1, 2016 at 12:49
  • 1
    What if origin-port is on different interface than destination port? Commented Sep 19, 2017 at 8:19

Based on Mark A.'s answer, I had to make a small tweak to get it to work for my Mac (at least on macOS Mojave Version 10.14.4)

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

That printf statement seems to be crucial. Otherwise the netcat command to connect to port 8000 will never actually try to connect, and the netcat command to listen on port 8001 will never actually listen on port 8001. Without the printf, every time I would try to connect to port 8001 I would get connection refused.

My assumption is that netcat must somehow block on stdin (maybe it's trying to read it for some reason) before actually doing any Socket operations. As such, without the printf statement writing to fifo a, the netcat command will never start listening on port 8001.

Note: I would have left an answer on Mark's post, but I don't have reputation yet.

  • 1
    This is the only answer that sort of worked for me. With two problems: 1) It only listens on the first request, even if I add -k. 2) It's as slow as molasses.
    – Dalin
    Commented Aug 24, 2021 at 13:30

This is a new way to tunnel two udp ports on server: https://github.com/9crk/udpeer

udpeer 8001 8002

To test:

nc -u xxxx.com 8001
nc -u xxxx.com 8002

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .