I thought I'd do a shorter article on catonmat this time. It goes hand in hand with my upcoming article series on "100% technical guide to anonymity" and it's much easier to write larger articles in smaller pieces. Then I can edit them together and produce the final article.

This article will be interesting for those who didn't know it already -- you can turn any Linux computer into a SOCKS5 (and SOCKS4) proxy in just one command:

ssh -N -D localhost

And it doesn't require root privileges. The ssh command starts up dynamic -D port forwarding on port 1080 and talks to the clients via SOCSK5 or SOCKS4 protocols, just like a regular SOCKS5 proxy would! The -N option makes sure ssh stays idle and doesn't execute any commands on localhost.

If you also wish the command to go into background as a daemon, then add -f option:

ssh -f -N -D localhost

To use it, just make your software use SOCKS5 proxy on your Linux computer's IP, port 1080, and you're done, all your requests now get proxied.

Access control can be implemented via iptables. For example, to allow only people from the ip to use the SOCKS5 proxy, add the following iptables rules:

iptables -A INPUT --src -p tcp --dport 1080 -j ACCEPT
iptables -A INPUT -p tcp --dport 1080 -j REJECT

The first rule says, allow anyone from to connect to port 1080, and the other rule says, deny everyone else from connecting to port 1080.

Surely, executing iptables requires root privileges. If you don't have root privileges, and you don't want to leave your proxy open (and you really don't want to do that), you'll have to use some kind of a simple TCP proxy wrapper to do access control.

Here, I wrote one in Perl. It's called tcp-proxy.pl and it uses IO::Socket::INET to abstract sockets, and IO::Select to do connection multiplexing.


use warnings;
use strict;

use IO::Socket::INET;
use IO::Select;

my @allowed_ips = ('', '', '', '');
my $ioset = IO::Select->new;
my %socket_map;

my $debug = 1;

sub new_conn {
    my ($host, $port) = @_;
    return IO::Socket::INET->new(
        PeerAddr => $host,
        PeerPort => $port
    ) || die "Unable to connect to $host:$port: $!";

sub new_server {
    my ($host, $port) = @_;
    my $server = IO::Socket::INET->new(
        LocalAddr => $host,
        LocalPort => $port,
        ReuseAddr => 1,
        Listen    => 100
    ) || die "Unable to listen on $host:$port: $!";

sub new_connection {
    my $server = shift;
    my $client = $server->accept;
    my $client_ip = client_ip($client);

    unless (client_allowed($client)) {
        print "Connection from $client_ip denied.\n" if $debug;
    print "Connection from $client_ip accepted.\n" if $debug;

    my $remote = new_conn('localhost', 55555);

    $socket_map{$client} = $remote;
    $socket_map{$remote} = $client;

sub close_connection {
    my $client = shift;
    my $client_ip = client_ip($client);
    my $remote = $socket_map{$client};

    delete $socket_map{$client};
    delete $socket_map{$remote};


    print "Connection from $client_ip closed.\n" if $debug;

sub client_ip {
    my $client = shift;
    return inet_ntoa($client->sockaddr);

sub client_allowed {
    my $client = shift;
    my $client_ip = client_ip($client);
    return grep { $_ eq $client_ip } @allowed_ips;

print "Starting a server on\n";
my $server = new_server('', 1080);

while (1) {
    for my $socket ($ioset->can_read) {
        if ($socket == $server) {
        else {
            next unless exists $socket_map{$socket};
            my $remote = $socket_map{$socket};
            my $buffer;
            my $read = $socket->sysread($buffer, 4096);
            if ($read) {
            else {

To use it, you'll have to make a change to the previous configuration. Instead of running ssh SOCKS5 proxy on, you'll need to run it on localhost:55555,

ssh -f -N -D 55555 localhost

After that, run the tcp-proxy.pl,

perl tcp-proxy.pl &

The TCP proxy will start listening on and will redirect only the allowed IPs in @allowed_ips list to localhost:55555.

Another possibility is to use another computer instead of your own as exit node. What I mean is you can do the following:

ssh -f -N -D 1080 other_computer.com

This will set up a SOCKS5 proxy on localhost:1080 but when you use it, ssh will automatically tunnel your requests (encrypted) via other_computer.com. This way you can hide what you're doing on the Internet from anyone who might be sniffing your link. They will see that you're doing something but the traffic will be encrypted so they won't be able to tell what you're doing.

That's it. You're now the proxy king!

Download tcp-proxy.pl

Download link: tcp proxy (tcp-proxy.pl)
Download URL: http://www.catonmat.net/download/tcp-proxy.pl
Downloaded: 12177 times

I also pushed the tcp-proxy.pl to GitHub: tcp-proxy.pl on GitHub. This project is also pretty nifty to generalize and make a program that redirects between any number of hosts:ports, not just two.

PS. I will probably also write "A definitive guide to ssh port forwarding" some time in the future because it's an interesting but little understood topic.


May 06, 2010, 23:59

Thanks for writing this! It broke it down very nicely, and I've been meaning to learn more about this kind of stuff for a while now. I am definitely interested in reading "A definitive guide to ssh port forwarding" when that comes around.

May 07, 2010, 17:51

Thanks for the comment. If you follow my blog you'll know when I start writing it. It will probably be part of 100% technical guide to anonymity as it has much to do with anonymity. I will also split it up in several parts because it's easier to write articles incrementally.

Nicely written, and easy to understand. Well done!
I have been using ssh -f -n -N -D for quite sometimes, and it really helps.

May 07, 2010, 17:51

The -n is an option I hadn't noticed. Thanks for mentioning it.

Anon Permalink
May 07, 2010, 13:38

SOCKS, besides being an abysmally awful protocol, is not supported by the majority of Internet software, so the advice you give is of limited usefulness. When I am confronted with a thoroughly hostile firewall, I depend on Net::Proxy. Accept no lesser substitutes.

May 07, 2010, 18:13

On Linux you can LD_PRELOAD trick to make any software use a socks proxy. Socksify does that, also tsocks does that.

Net::Proxy indeed is a good one. Much better than my primitive tcp-proxy. But I wrote it out of curiosity, hadn't used IO::Socket and IO::Select in ages and wanted to refresh my knoweldge.

May 11, 2010, 21:07

If you want to make some SOCKS proxy available to all your applications, possibly better way than using tsocks is implementing iptables-based solution with the help of redsocks (git repository). See my tip Making SOCKS proxy transparent for example.

Another useful (in this context) ssh option is -g, but it requires turning GatewayPorts on in sshd_config.

anonn Permalink
July 19, 2017, 04:04

what a delightfully stupid comment

Wayne Scott Permalink
May 07, 2010, 14:09

You might want to checkout this command I have been using:


May 07, 2010, 18:04

Wow, that is awesome software. Thanks for linking. I'm going to try it!

May 07, 2010, 14:42

great tips.
if sshd port not 22,use "-p "
ssh -f -p your_sshd_port -n -N -D bindip:1080 localhost

May 07, 2010, 18:04

Good tip. Thanks for writing it!

just curious Permalink
May 07, 2010, 16:30

How much money do you make through ads?

May 07, 2010, 18:08

Not much.

May 07, 2010, 17:10

yes - thats a great feature of the ssh client. I used it quite often when i was too lazy to do vpn configs for some nets behind router - just running sshd with correct restriction on the gateway will save you alot of time (at least saved me, cause i am not admin :). But for some time I am just linking some remote ports on the localhost:
ssh -L 8080:localhost:80 someuser@somehost
Its quite usefull too if you have remote server behind router with access only to ssh port.
About the article - very usefull - thought about "-f" option and how nice its usage is

May 07, 2010, 18:12

Yes, local port forwarding is awesome. I am going to describe it in more detail in my definitive guide to ssh port forwarding.

Paul M. Permalink
May 07, 2010, 17:55

If you're concerned about limiting access to your ssh pseudo-proxy and it's running locally, why not just have ssh bind to localhost, rather than

May 07, 2010, 18:11

For example, you want to give your friend socks5 access but you don't have root on the machine and you don't want everyone to have open access to it. Then as I described, you can start the socks5 proxy on, let's say, port 55555, and provide ip based access control via tcp-proxy.pl which would listen on port and forward requests to localhost:55555.

Paul Permalink
May 08, 2010, 08:19

>Turn any Linux computer into SOCKS5 proxy
Iptables, ok - but Perl and ssh on "any Linux computer"?!

May 08, 2010, 14:24

Yeah, Perl and ssh is almost on any Linux computer.

Sarek Permalink
April 24, 2012, 17:51

Hi. I have a question about a problem I am trying to solve.
Your SOCKS5 post.. I did it. It works with TCP. It doesn't work with UDP. How do I get it to work with UDP? Thank you.
If it's not possible because SSH is


, I understand. I think this is really great and I really like.

Satish Permalink
May 08, 2010, 10:56

I have been trying to proxy my IE instance in Win 7 to go through a similar setup via putty but unfortunately IE -> Options -> Connections -> Settings is disabled. I still haven't figured out how to get this working with IE though :(

May 08, 2010, 14:25

You must be using a limited user account.

Anonymous Permalink
May 08, 2010, 17:18

If you're into anonymity, check http://www.i2p2.de/

beneedy Permalink
May 09, 2010, 21:45

I think I have it partially working, but when I configure my browser with the proxy settings I just get a blank white screen to whatever website I am visiting. The webpage says it is done loading, but just no content... What do you think the problem is?

May 11, 2010, 14:07

Nice , but i use python script not perl :D.

kangu Permalink
May 11, 2010, 18:27

Thanks petter it's well written and easy to follow on with!

mwicat Permalink
May 13, 2010, 08:10

when speaking about source host ACLs, socat utility fits perfectly in this task:
socat tcp-listen:4444,range=,reuseaddr,fork tcp:localhost:3333

...to relay between and localhost:3333 passing only, range= for whole network and finally utilize the power of tcp wrappers with:
socat tcp-listen:4444,allow-table=iplist,reuseaddr,fork tcp:localhost:3333
# iplist contents:

May 13, 2010, 12:50

A lot of work which could be simplified. U use windows too much ;)

$ sudo -i
# iptables -N proxy_allowed
# iptables -A proxy_allowed -s [ALLOWED_IP] -j RETURN
# iptables -A proxy_allowed -j DROP
# iptables -A INPUT --syn --dport 1080 -j proxy_allowed
# exit
$ ssh -g -D 1080 [REMOTE_IP]

no wrapper is required. if u wish to harden the solution use some knocking (or ping with specified packet length and iptables "recent" module) and/or ip-mac association.

socks does not offer much, to redirect dns or udp traffic it is better to use ppp over ssh or vpn (which I consider preferred).. openvpn is free and there is extremally simple windows gui client.

take care!

ps. python > perl ;P

Alphazo Permalink
July 08, 2010, 07:44

100% agree... "-D 1080" is all what you need. I like to add -p 443 to in order to make the SSH traffic less visible ;)

Then to avoid DNS leaks under Firefox, just make sure to set the two following variables to 1 under about:config.

network.proxy.network.proxy.socks_remote_dns = 1
network.proxy.socks_remote_dns = 1

When I Wireshark the above config I can only see HTTPS traffic even when typing non-working URLs.

ctrl_ Permalink
May 18, 2010, 07:57

Is there a log file where I can see the traffic when doing this?

Ashok Permalink
August 19, 2010, 11:50

Is this http://wiki.przemoc.net/tips/linux#making_socks_proxy_transparent are same as SocksCap?

peter Permalink
August 25, 2010, 12:43

Which ip does represents?

August 25, 2010, 18:57

All IPs.

Hello @pkrumins. I have bookmarked your page and as soon as I am a bit more organized i will peruse your web site and incorporate any information you provide into my spanish language proxy guide.

by the way, would you mind editing your post to include the commands to connect exclusively to localhost as i have my socks proxy set up to only accept connections from localhost. you should be able to see my email. for the rest there are effective antispam features that do not require captcha like akismewhatosever.


October 24, 2010, 07:33

I am very appreciative of this informative piece. Thank you very much I will be sure to use this in my soon to be proxy server at my residence.

ali Permalink
November 17, 2010, 21:55

thank you for this awesome topic ,but i just wanna know that
is there a way that i can use this little command to have
a socks5 server with authentication i mean(username and pass)
rather than IPs
help me please

Dennis Permalink
December 17, 2010, 14:30

Trying to use the basic ssh command on ec2 (ubuntu image) but getting a "Permission denied (publickey)" error.
Any tips on what the problem is?
Actually, i tried it on my own ubuntu machine (linux via virtualbox) and got the same error.
I did not see other comments reporting this type of error so not sure what to do next.

jack Permalink
February 05, 2013, 03:54

you need to initiate the ssh connection on the localhost using the .pem certificate just like you connect to the ec2 server

Davoud Permalink
June 19, 2013, 09:30

ssh -f -N -D -i keyfile.pem localhost

(Make sure its access privilege is 0600)

008 Permalink
December 25, 2010, 22:05

Its useful for me and many ppl, try write script for PAM auth with this mothod, and many many ppl will be HAPPY!

mary xmas!

Ravi Permalink
December 27, 2010, 13:50

I am told to use a socks5 proxy set up on Host ABC, port 1080. How do I get scp to use this socks5 proxy?

nexed Permalink
August 12, 2011, 19:10

Not sure why you would need to run any kind of tcp-proxy script or iptables to protect the connection....

have proxy ssh listen on localhost:1080 and use something like MyEnTunnel to create an ssh tunnel to the server.

once the tunnel is established, configure your software to your localhost / port you configured and done.

Not only does this provide direct credential protection and eliminates the need for fw but also encrypts the connection to the proxy server so your ISP doesn't know what you are doing....

October 07, 2011, 15:07

but , can i use password protecting for SOCKS proxy?

November 25, 2011, 19:00

When using this script, the CPU usage slowly crawls up until eventually it hits 100%. I don't know if some bot's found my server and there are hundreds using the proxy or what, but I would like some tips on troubleshooting this. For the time being I have a script that kills the proxy and starts it back up if CPU usage is too high.

December 12, 2011, 12:20

I usually don't comment in peoples blog, but I found your article very appreciating so replying to say "Thanks!"

This is exactly what I was looking for and instead of some big tutorial, you made my work done in less then a minute :)

Pawan Permalink
January 08, 2012, 12:16

hi i m newbie in Linux and trying to access internet via Linux (socks & http)
my squid working perfect
and i try your scripts to run socks also on CENTOS i got an error :

ssh -N -D localhost
ssh: localhost: Name or service not known

please help me how i can access internet through socks...

Drift Permalink
February 18, 2012, 13:51

Hello, im having problem with proxing i have 10 ip adresses on my root and when i start proxi server any ip adress i put of that 10 it will be same one,anyone know how to fix that?Thanks

DAV Permalink
February 24, 2012, 10:05

Is there any way to get this to work from outside of the private subnet and add some sort of authentication? I would like to access my server at the office from home via a socks service but don't want it open to the entire world. I have a live IP on the server. My home system runs ADSL with a dynamic IP address so I can't use that as a restriction. I was thinking of a username/password scenario?

DAV Permalink
February 24, 2012, 10:07

In case the above is unclear. I would like to have my home network tunnel through my office server for internet access. :)

Maverick Permalink
May 19, 2012, 04:39

Hi Peter. Great post. I have been working on something for a couple of days. Maybe you can help. I want to run a SOCKS proxy on a Linux machine which listens on port 1080 and forwards all incoming data to another SOCKS proxy running on How can I do that?

May 22, 2012, 22:46

You can't do that easily. You need to do something called proxy chaining. It will look like this:

[Your computer]->[Linux running socks5 on 1080]->[ running socks5 on 22]

What you'll need to do is open a connection from [Your computer] to [Linux running socks5 on 1080], and then ask this socks5 proxy to open a connection to [ running socks5 on 22]. And now you'll use this connection for your purposes.

Ana Gallardo Permalink
June 29, 2012, 12:33

Hello Peter and thank you for your post!!

I have a captive portal.

I need to intercept a tcp connection, do some actions and fordward the connection.

Now I only intercept http connections, and then I redirect that conection:

sub redirect {
my ( $self, $peer, $url ) = @_;
$self->log( 10, "GATEWAY : redirigimos a $url" );
"HTTP/1.1 302 Moved\r\n",
"Location: $url\r\n\r\n", qq{


You should be redirected now. If not, click here.


So, I would like to do a general redirect, not only a http redirect.

I would appreciate it if you would give me some ideas :)

Thank you very much in advance and sorry for my english.

zak Permalink
August 15, 2012, 18:54


Hello Mate,

I have a dedicated server with 20 additional ips

I would ideally like to convert these ips to socks 5 to receive and send data via ports 5001 / 5000 udp / tcp

My questions now are -

1- which Lunix OS would i need.
2- How will i configure these ips.
3- Will anyone here be willing to help someone in need.


John Doe Permalink
November 22, 2012, 03:20

I received the following error:

ssh: connect to host localhost port 22: Connection refused

Justin Permalink
November 22, 2012, 14:40

Me too.

jon Kolman Permalink
March 04, 2013, 00:17

Is it possible to setup a socks5 proxy on an actual server? For some reason I can't connect to my proxy while at school. I have verizon fios and the router isn't port forwarding port 2100.

Davoud Permalink
June 19, 2013, 09:41

Hi Peter
I've setup the socks proxy server successfully on an ec2 instant. However I can not bypass the filtering for blocked website (I live in Iran). It only works for https website as if the connection is not encrypted.

Ryan G Permalink
August 29, 2013, 19:37

email me ill give you a proxy to use

Ryan G Permalink
August 29, 2013, 19:36

that is one of the best articles ive seen that is some good stuff right there!

Marek Permalink
October 24, 2013, 11:44

Very nice, it would be nice also write mentioned "A definitive guide to ssh port forwarding" or anonymity articles. Thank you

cdtoad Permalink
November 04, 2013, 23:22

So can you add username/password to secure the proxy if you're going to be out & about?

Elans Permalink
November 13, 2013, 17:32

Thanks for the article, very interesting.

John Permalink
December 07, 2013, 19:41

you can also use "ssh -fND localhost"

Salman Hyder Permalink
February 15, 2014, 20:04

Thank you for your tutorial. Everything is working fine, just when i'm using proxy on Windows XP SP3 and browsing for youtube it returns the localhost of my linux computer.

Charles Permalink
February 15, 2014, 20:20

Hey, I'm new to Linux software as well as hosting proxy servers. This is a very nice tutorial from what I can gather.
However, I'd be grateful if someone could help me in more detail. Okay, so I've done as the tutorial says but when I try to use this as a proxy it simply doesn't work. When I test the port it says that port 1080 is open. Could someone give me a hint as to what they problem may be?

March 21, 2014, 19:25

Thank you for clean and simply tutorial. I've hosted my website http://www.loadezi.com on my Ubuntu which i'm also using for proxy, every thing going well except when i'm entering www.youtube.com from any cleint proxy returns my website whereas is shows youtube.com in address bar but redirects me to my website which is hosted on proxy server. help resolve this issue and help me to run youtube.com

asjdlfka Permalink
April 20, 2014, 03:49

Hi I need it to do that but when i put in ssh -N -D i get error "bad dynamic forwarding specification" please help apparently nobody else in the comments has that

John Permalink
May 16, 2014, 10:57

try ssh -N -D localhost (remove the : between 1080 and localhost)

Umesh Permalink
July 13, 2015, 11:00

Hey, with IPv4: ssh -fND localhost works.
I need help with Command to allow IPv6 Addresses to use SOCKS 4&5.

Kindly do the needful.


October 27, 2015, 03:57

the perl script is really helpful, thanks for sharing!

rockbird Permalink
May 03, 2016, 18:40


I have a VPS with one ipv4 ip and plenty of ipv6 ips.

i would like to setup Dante to work as a socks proxy server in my server.

I need to assign different port to each ipv6 port.

Now i can use ipv4 without a problem and when i connect with my server and check my ip it successfully show my ipv4 ip.

I didn't wanna show my ipv4 to the rest of the world, but only my ipv6 ip .

And also assign different ports to different ipv6 ips , which mean: work with ipv6 ip number 1 work with ipv6 ip number 2 work with ipv6 ip number 2
How can i do this with Dante?

Zak Permalink
December 29, 2016, 11:41

Hello, I tried that tutorial on openwrt but it didn't work.

rzgar Permalink
June 27, 2017, 11:04

hi i have a question can we repeat socks5 proxy command with other port numbers? i mean i want to have socks5 listening on port range of 30000 to 30500 is this possible with this tutorial?
im sry im new in linux stuff.

Igor Permalink
December 14, 2017, 06:18

Thanks, very useful. Is it possible to implement login-password in perl wrapper?

December 19, 2018, 09:26

This is a wonky way to set this up. The better way is to open port 22 on your home Linux box and from a remote location do: ssh -D 1080


Then configure your browser to use, localhost:1080 as a socks proxy. You're done. You've created a secure SSH tunnel to your home machine. Any sniffed traffic will look like encrypted SSH traffic. The way he has this setup, opening port 1080 sends all you're traffic (i.e. HTTP requests) in plain text.

Leave a new comment

(why do I need your e-mail?)

(Your twitter handle, if you have one.)

Type the word "browser_216": (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.