Opened 7 years ago
Last modified 6 months ago
#7875 new defect
debian obfsproxies can't advertise ports under 1024
Reported by: | arma | Owned by: | asn |
---|---|---|---|
Priority: | Medium | Milestone: | Tor: unspecified |
Component: | Core Tor/Tor | Version: | |
Severity: | Normal | Keywords: | tor-bridge, tor-pt, privileges, low-ports, review-group-34 |
Cc: | asn, mo, weasel, torvlnt33r@…, mttp, dgoulet, phw | Actual Points: | |
Parent ID: | Points: | ||
Reviewer: | Sponsor: |
Description
We don't have (m)any obfsproxies running on port 443. That's a shame.
But if you're on debian and want to follow our instructions (https://www.torproject.org/projects/obfsproxy-debian-instructions), even if you know how to set up port forwarding, there's no way for your Tor to advertise that your obfsproxy is listening on a low-numbered port.
One option is for Tor to launch obfsproxy as root before Tor drops privs, and then obfsproxy binds its low-numbered port and then drops privs too. That sounds awful.
Another option is to complexify ServerTransportListenAddr, or add a new config option like it, so we can tell Tor what address to pretend obfsproxy listens on. That sounds less awful but still not great.
Other options? It would be ideal if the Tor and obfsproxy debs could somehow do this themselves, since an "add this line to your iptables" component in our instructions places it out of reach of most users.
Child Tickets
Change History (29)
comment:1 follow-up: 4 Changed 7 years ago by
comment:2 Changed 7 years ago by
Component: | Tor → Obfsproxy |
---|---|
Owner: | set to asn |
comment:3 Changed 7 years ago by
Component: | Obfsproxy → Tor |
---|
comment:4 follow-up: 5 Changed 7 years ago by
Cc: | torvlnt33r@… added |
---|
Replying to flaushy:
You can grant priviledges to do so via setcap. (included in libcap2-bin)
setcap 'cap_net_bind_service=+ep' /path/to/obfsproxy
After granting this capability you are able to run obfsproxy with user rights on ports <1024
This is not working for me, maybe because obfsproxy is now (version 0.2.1) a (Python) script (see caveat 2 in the first answer on http://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-1024-on-l ).
Indeed, with a downgrade of obfsproxy to 0.1.4, it works. (But obfs3 would be missing).
comment:5 Changed 7 years ago by
Replying to torvlnt33r:
Replying to flaushy:
You can grant priviledges to do so via setcap. (included in libcap2-bin)
setcap 'cap_net_bind_service=+ep' /path/to/obfsproxy
After granting this capability you are able to run obfsproxy with user rights on ports <1024
This is not working for me, maybe because obfsproxy is now (version 0.2.1) a (Python) script (see caveat 2 in the first answer on http://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-1024-on-l ).
Ok, it works if you make a copy of the script interpreter and give it the capabilities, as described as workaround in above reference.
On my system, python is a symbolic link to /usr/bin/python2.7. So:
cp /usr/bin/python2.7 /path/to/copy/of/python2.7
setcap 'cap_net_bind_service=+ep' /path/to/copy/of/python2.7
and add the interpreter into the ServerTransportPlugin line in torrc:
ServerTransportPlugin obfs2,obfs3 exec /path/to/copy/of/python2.7 /usr/bin/obfsproxy managed
comment:6 Changed 7 years ago by
The setcap
solution requires the operator to run the setcap command as root, right? I guess that's equally "bad" (from the point of view of a non-technical operator) to an iptables command that redirects traffic from the low order port to the obfsproxy port.
arma's ideas still stand (because they don't require operator intervention) but they both still sound awful :(
comment:7 Changed 7 years ago by
Actually, my option two doesn't sound so bad. It's basically a config option to specify what port Tor should advertise, as opposed to what port Tor should tell obfsproxy to listen on.
comment:8 Changed 7 years ago by
Hey, another (bad but not horrible) option is to for Tor to grow a new "redirect" conn type, which it opens when it starts, and which funnels bytes from incoming conns to the specified destination port, maybe using our 'linked conns' notion. That would be sort of like running the iptables rule, but more portable and less scary for novice operators.
comment:9 Changed 6 years ago by
Cc: | mttp added |
---|
comment:10 follow-up: 11 Changed 6 years ago by
Can the difference between options 2 and 3 be clarified? I think I read option 2 and I thought it was describing the same design as option 3, but apparently not if option 3 is a distinct option.
comment:11 Changed 6 years ago by
Replying to cypherpunks:
Can the difference between options 2 and 3 be clarified? I think I read option 2 and I thought it was describing the same design as option 3, but apparently not if option 3 is a distinct option.
Seems like pretty much the same idea to me. One comment describes the torrc side, the other describes how it could work using Tor's linked conns.
comment:12 follow-up: 14 Changed 6 years ago by
Cc: | dgoulet added |
---|
#8195 might also be a step forward. It uses Linux capabilities(7)
to let Tor bind to low listening ports even after it has dropped privs. David told me that Linux capabilities also do inheritance, so it might be possible for our PT processes to inherit this capability themselves.
comment:13 Changed 6 years ago by
Cc: | yawning added |
---|
comment:14 Changed 5 years ago by
Replying to asn:
#8195 might also be a step forward. It uses Linux
capabilities(7)
to let Tor bind to low listening ports even after it has dropped privs. David told me that Linux capabilities also do inheritance, so it might be possible for our PT processes to inherit this capability themselves.
Yawning posted some updates on this from the dev meeting:
At the dev meeting I was talking to dgoulet about having tor do the appropriate work to preserve the CAP_NET_BIND_SERVICE when dropping root so all PTs transparently get this capability. He mentioned difficulties with our python PTs, probably because the ServerTransportPlugin line was pointing directly at the script and it was getting invoked via the #! handler in the kernel. It may be possible that this "just works" if the ServerTransportPlugin line pointed at the python interpreter instead, but if it does not, this will probably require a kernel patch, that won't ever get accepted upstream.
from https://lists.torproject.org/pipermail/tor-dev/2014-July/007139.html
comment:15 Changed 5 years ago by
And for completeness, this is the line I'm using in my bridge to make obfs3 reachable on port 443
:
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 25429
where the actual port of obfs3 is 25429
.
comment:16 Changed 5 years ago by
Status: | new → needs_review |
---|
arma pointed out this afternoon that dgoulet's patches for #8195 might be applicable to fixing this. It would need testing for exec
ing PT ServerTransportPlugin
lines for both Go and Python PTs (with /usr/bin/python
or via the #!
line, as asn pointed out above).
comment:17 follow-up: 19 Changed 5 years ago by
In the bright new obfs4proxy feature, setcap
ing the obfs4proxy binary behaves as expected, so any/all of:
- #8195 assuming tor starts with sufficiently elevated privileges.
- The admin manually
setcap
ing the obfs4proxy binary. - The package automagically handling this somehow (don't ask me how).
will solve this for obfs2/3/4. FTE/ScrambleSuit still use the old python codebase so those require further investigation. Personally, I don't view manually calling setcap
on installation/update as a huge hassle, but then again my bridge deployment procedure consists of scp
ing the binary over, and running a shell script, so I'm probably not the person to make decisions here.
The fact that obfs4proxy works with setcap
is also documented in the README.md file, so we're in a better situation than previously, and when we do our bridge deployment documentation revamp, we can also highlight this there.
comment:18 Changed 5 years ago by
setcapping the binary would allow any user to listen on any low port using the binary. I don't think it's a good general purpose solution for a distribution.
comment:19 follow-up: 20 Changed 5 years ago by
Replying to yawning:
FTE/ScrambleSuit still use the old python codebase so those require further investigation.
setcap
ing Python scripts also works just fine. (We used to do it with OONI to give raw socket capabilities without giving the script root privileges.)
comment:20 follow-up: 21 Changed 5 years ago by
Replying to weasel:
setcapping the binary would allow any user to listen on any low port using the binary. I don't think it's a good general purpose solution for a distribution.
I agree. IMO it's not a package's place to dictate security policy, at least not for something like obfs4proxy
. I still think it should be mentioned along with a detailed port forwarding example in our documentation, since those are the two current solutions for this issue.
Replying to isis:
Replying to yawning:
FTE/ScrambleSuit still use the old python codebase so those require further investigation.
setcap
ing Python scripts also works just fine. (We used to do it with OONI to give raw socket capabilities without giving the script root privileges.)
It shouldn't unless you were setcap
ing the python binary....
As a simple test:
#!/usr/bin/python2 import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('127.0.0.1', 9)) s.listen(5)
Baseline behavior:
ypres :: ~ % ./discard.py Traceback (most recent call last): File "./discard.py", line 4, in <module> s.bind(('127.0.0.1', 9)) File "/usr/lib/python2.7/socket.py", line 224, in meth return getattr(self._sock,name)(*args) socket.error: [Errno 13] Permission denied ypres :: ~ % sudo ./discard.py ypres :: ~ %
setcap
the script along with the #!
handler, or /usr/bin/python2 discard.py
:
ypres :: ~ % sudo setcap 'cap_net_bind_service=+ep' /home/yawning/discard.py ypres :: ~ % ./discard.py Traceback (most recent call last): File "./discard.py", line 4, in <module> s.bind(('127.0.0.1', 9)) File "/usr/lib/python2.7/socket.py", line 224, in meth return getattr(self._sock,name)(*args) socket.error: [Errno 13] Permission denied
Use a python interpreter with elevated privileges:
ypres :: ~ % cp /usr/bin/python2 ./python2-setcapped ypres :: ~ % sudo setcap 'cap_net_bind_service=+ep' /home/yawning/python2-setcapped ypres :: ~ % ./python2-setcapped discard.py ypres :: ~ %
dgoulet's patch *should* produce behavior identical to the last case, unless there's other weirdness going on.
comment:21 Changed 5 years ago by
Replying to yawning:
It shouldn't unless you were
setcap
ing the python binary....
Whoops, you're correct. I misremembered… we used to create Python virtualenvs, then setcap
the copy of the Python binary in the virtualenv.
comment:22 Changed 3 years ago by
Keywords: | tor-pt privileges low-ports added |
---|---|
Severity: | → Normal |
comment:23 Changed 22 months ago by
Milestone: | Tor: unspecified → Tor: 0.3.4.x-final |
---|
Move all needs_review tickets without a release to 0.3.4
comment:24 Changed 22 months ago by
Keywords: | review-group-34 added |
---|
comment:25 Changed 21 months ago by
Milestone: | Tor: 0.3.4.x-final → Tor: unspecified |
---|---|
Status: | needs_review → new |
comment:26 Changed 21 months ago by
Cross-referencing #18356 / Debian #865495, which say that these days, setcap
alone is not enough: you also have to work around systemd hardening. Specifically, you have to set NoNewPrivileges=no
in /lib/systemd/system/tor@default.service and /lib/systemd/system/tor@.service and then run systemctl daemon-reload
. This has been the case since 0.2.7.4-rc-1 (October 2015).
comment:27 Changed 21 months ago by
Cc: | yawning removed |
---|
comment:28 Changed 21 months ago by
This might be relevant as a howto: https://lorenzo.mile.si/2017/02/running-obfs4-tor-bridge-on-port-80-443/
comment:29 Changed 6 months ago by
Cc: | phw added |
---|
cc'ing phw because we might want to work on this ticket as part of the obfs4 operator ux work (at least, say, documenting the workaround).
You can grant priviledges to do so via setcap. (included in libcap2-bin)
setcap 'cap_net_bind_service=+ep' /path/to/obfsproxy
After granting this capability you are able to run obfsproxy with user rights on ports <1024
http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html