Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'd like to accept connections briefly for development when I'm NATed, and so I'm attempting to do this:

$ ssh ubuntu@example.org -R 80:localhost:80

Which fails as I'm trying to bind a port that is to low:

Warning: remote port forwarding failed for listen port 80

So I've discovered that I can do setcap 'cap_net_bind_service=+ep' /my/application to allow it to listen to ports lower than 1024. So I've got this in my suders crontab:

@reboot setcap 'cap_net_bind_service=+ep' /usr/sbin/sshd

But it's still not letting me bind on port 80. What am I doing wrong? I'm just going to use nginx to proxy to 8080 or iptables or something instead, but I'm still curious why what I was trying to do didn't work.

share|improve this question
    
What filesystem are you using? Not all filesystems support setcap. –  Gilles Jun 24 '12 at 1:20
    
@Gilles I'm using ext4, it's the default Ubuntu image off AWS and I haven't done anything fancy with it. –  Kit Sunde Jun 24 '12 at 7:03
    
It sounds as if you are root on the box. Maybe I'm ignorant but shouldn't just executing the first line as root solve your problem? –  Christian Jun 25 '12 at 7:26
    
@Christian You can't bind on <1024 without sudo by design. Like how you cannot apt-get install foo without first doing sudo. –  Kit Sunde Jun 25 '12 at 8:23
    
@KitSunde Yeah, root is an un-Ubuntuic way of saying sudo. It's a user that has all the privileges that a normal user only gets when doing sudo. root is also sometimes called the superuser. So basically my question to you was: You seem to be able to do sudo on the box, why can't you in this case? –  Christian Jun 25 '12 at 12:14
show 6 more comments

2 Answers

up vote 3 down vote accepted

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

share|improve this answer
    
Oh I wasn't expecting that, this most certainly would answer my question. –  Kit Sunde Jul 30 '12 at 15:29
add comment

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

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.