How can I set up a remote port forward on port 80 to my localhost with the help of setcap?

OpenSSH will flat-out refuse to bind to privileged ports unless the user id of the logged in user is 0 (root). The relevant lines of code are:

if (!options.allow_tcp_forwarding ||
    no_port_forwarding_flag ||
    (!want_reply && listen_port == 0) ||
    (listen_port != 0 && listen_port < IPPORT_RESERVED &&
    pw->pw_uid != 0)) {
        success = 0;
        packet_send_debug("Server has disabled port forwarding.");

Source: http://www.openssh.com/cgi-bin/cvsweb/src/usr.bin/ssh/serverloop.c?annotate=1.162 lines 1092-1098

If you're curious, pw is of type struct passwd * and on linux is defined in /usr/include/pwd.h


This is a great use case for socat.

First, do a remote forward to port 8080 (or any other allowed port) of the remote machine:

ssh [email protected] -R 8080:localhost:80

Then on the remote machine, map port 80 to port 8080:

sudo socat TCP-LISTEN:80,fork TCP:localhost:8080

Notes:

As suggested by Dirk Hoffman, these two commands can be combined into a single line:

ssh -t [email protected] -R 8080:localhost:80 sudo socat TCP-LISTEN:80,fork TCP:localhost:8080

(The -t is necessary in case you need an interactive terminal to enter your sudo password.)


I meet the similar problem, so the solution I ended up is to add DNAT rule to the OUTPUT chain of nat table:

iptables -t nat -A OUTPUT -d 127.0.0.0/8 -p tcp --dport 80 \
-j DNAT --to-destination :8080

This rule effectively replaces the destination port 80 with 8080 for all locally generated tcp packets.

If you wish to allow any incoming connections to be forwarded as well then add one extra rule to the PREROUTING nat chain:

iptables -t nat -A PREROUTING -d 10.0.0.200 -p tcp --dport 80 \
-j REDIRECT --to-port 8080

where 10.0.0.200 is the IP address of the interface that should be forwarding incoming connections to your web service