From 2a76b520d5a260725d552cf7cd78dba35b20857a Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Tue, 10 Oct 2017 07:07:28 +0200 Subject: [PATCH 1/3] Add better documentation of transparent proxy support. This allows for some more generalized configs. You don't need to specify ports anymore and still can connect directly to the running services if you want. It also allows you to use "localhost" as destination in your sslh config, something that wasn't possible with the old scheme. --- README.md | 70 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d23c107..dae9819 100644 --- a/README.md +++ b/README.md @@ -236,30 +236,60 @@ The example connects to HTTPS on 4443 -- adapt to your needs ; I don't think it is possible to have `httpd` listen to 443 in this scheme -- let me know if you manage that: - # iptables -t mangle -N SSLH - # iptables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 22 --jump SSLH - # iptables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 4443 --jump SSLH - # iptables -t mangle -A SSLH --jump MARK --set-mark 0x1 - # iptables -t mangle -A SSLH --jump ACCEPT - # ip rule add fwmark 0x1 lookup 100 - # ip route add local 0.0.0.0/0 dev lo table 100 + # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination + $ sysctl -w net.ipv4.conf.default.route_localnet=1 + $ sysctl -w net.ipv4.conf.all.route_localnet=1 + + # DROP martian packets as they would have been if route_localnet was zero + # Note: packets not leaving the server aren't affected by this, thus sslh will still work + $ iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP + $ iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP + + # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") + $ iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f + + # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) + $ iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f + + # Configure routing for those marked packets + $ ip rule add fwmark 0x1 lookup 100 + $ ip route add local 0.0.0.0/0 dev lo table 100 Tranparent proxying with IPv6 is similarly set up as follows: - # ip6tables -t mangle -N SSLH - # ip6tables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 22 --jump SSLH - # ip6tables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 4443 --jump SSLH - # ip6tables -t mangle -A SSLH --jump MARK --set-mark 0x1 - # ip6tables -t mangle -A SSLH --jump ACCEPT - # ip -6 rule add fwmark 0x1 lookup 100 - # ip -6 route add local ::/0 dev lo table 100 + # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination + $ sysctl -w net.ipv4.conf.default.route_localnet=1 + $ sysctl -w net.ipv4.conf.all.route_localnet=1 -Note that these rules will prevent from connecting directly -to ssh on the port 22, as packets coming out of sshd will be -tagged. If you need to retain direct access to ssh on port -22 as well as through sslh, you can make sshd listen to -22 AND another port (e.g. 2222), and change the above rules -accordingly. + # DROP martian packets as they would have been if route_localnet was zero + # Note: packets not leaving the server aren't affected by this, thus sslh will still work + $ ip6tables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP + $ ip6tables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP + + # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") + $ ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f + + # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) + $ ip6tables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f + + # Configure routing for those marked packets + $ ip -6 rule add fwmark 0x1 lookup 100 + $ ip -6 route add local 0.0.0.0/0 dev lo table 100 + +Explanation: +To be able to use `localhost` as destination in your sslh config along with transparent proxying +you have to allow routing of loopback addresses as done above. +This is something you usually should not do (see [this stakoverflow post](https://serverfault.com/questions/656279/how-to-force-linux-to-accept-packet-with-loopback-ip/656484#656484)) +The two `DROP` iptables rules emulate the behaviour of `route_localnet` set to off (with one small difference: +allowing the reroute-check to happen after the fwmark is set on packets destined for sslh). +See [this diagram](https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg) for a good visualisation +showing how packets will traverse the iptables chains. + +Note: +You have to run `sslh` as dedicated user (in this example named `sslh`, too), to not mess up with your normal networking. + +These rules will allow you to connect directly to ssh on port +22 (or to any other service behind sslh) as well as through sslh on port 443. FreeBSD: From 74767cb7819939b5d689bfc59b09858c699f9c59 Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Tue, 10 Oct 2017 07:22:44 +0200 Subject: [PATCH 2/3] Some cleanup --- README.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index dae9819..4111efe 100644 --- a/README.md +++ b/README.md @@ -231,63 +231,61 @@ Linux: give it `CAP_NET_ADMIN` capabilities (see appropriate chapter) or run it as root (but don't do that). -The firewalling tables also need to be adjusted as follow. -The example connects to HTTPS on 4443 -- adapt to your needs ; -I don't think it is possible to have `httpd` listen to 443 in +The firewalling tables also need to be adjusted as follows. +I don't think it is possible to have `httpd` and `sslh` both listen to 443 in this scheme -- let me know if you manage that: - # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination + $ # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination $ sysctl -w net.ipv4.conf.default.route_localnet=1 $ sysctl -w net.ipv4.conf.all.route_localnet=1 - # DROP martian packets as they would have been if route_localnet was zero - # Note: packets not leaving the server aren't affected by this, thus sslh will still work + $ # DROP martian packets as they would have been if route_localnet was zero + $ # Note: packets not leaving the server aren't affected by this, thus sslh will still work $ iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP $ iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP - # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") + $ # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") $ iptables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f - # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) + $ # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) $ iptables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f - # Configure routing for those marked packets + $ # Configure routing for those marked packets $ ip rule add fwmark 0x1 lookup 100 $ ip route add local 0.0.0.0/0 dev lo table 100 Tranparent proxying with IPv6 is similarly set up as follows: - # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination + $ # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination $ sysctl -w net.ipv4.conf.default.route_localnet=1 $ sysctl -w net.ipv4.conf.all.route_localnet=1 - # DROP martian packets as they would have been if route_localnet was zero - # Note: packets not leaving the server aren't affected by this, thus sslh will still work + $ # DROP martian packets as they would have been if route_localnet was zero + $ # Note: packets not leaving the server aren't affected by this, thus sslh will still work $ ip6tables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP $ ip6tables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP - # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") + $ # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") $ ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f - # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) + $ # Outgoing packets that should go to sslh instead have to be rerouted, so mark them accordingly (copying over the connection mark) $ ip6tables -t mangle -A OUTPUT ! -o lo -p tcp -m connmark --mark 0x01/0x0f -j CONNMARK --restore-mark --mask 0x0f - # Configure routing for those marked packets + $ # Configure routing for those marked packets $ ip -6 rule add fwmark 0x1 lookup 100 $ ip -6 route add local 0.0.0.0/0 dev lo table 100 Explanation: To be able to use `localhost` as destination in your sslh config along with transparent proxying you have to allow routing of loopback addresses as done above. -This is something you usually should not do (see [this stakoverflow post](https://serverfault.com/questions/656279/how-to-force-linux-to-accept-packet-with-loopback-ip/656484#656484)) +This is something you usually should not do (see [this stackoverflow post](https://serverfault.com/questions/656279/how-to-force-linux-to-accept-packet-with-loopback-ip/656484#656484)) The two `DROP` iptables rules emulate the behaviour of `route_localnet` set to off (with one small difference: allowing the reroute-check to happen after the fwmark is set on packets destined for sslh). See [this diagram](https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg) for a good visualisation showing how packets will traverse the iptables chains. Note: -You have to run `sslh` as dedicated user (in this example named `sslh`, too), to not mess up with your normal networking. - +You have to run `sslh` as dedicated user (in this example the user is also named `sslh`), to not mess up with your normal networking. These rules will allow you to connect directly to ssh on port 22 (or to any other service behind sslh) as well as through sslh on port 443. From d243d36add906472e05a56980f217ec04d4f25e0 Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Tue, 10 Oct 2017 07:36:09 +0200 Subject: [PATCH 3/3] Fix ipv6 config copy-paste errors --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4111efe..048ea82 100644 --- a/README.md +++ b/README.md @@ -257,13 +257,14 @@ this scheme -- let me know if you manage that: Tranparent proxying with IPv6 is similarly set up as follows: $ # Set route_localnet = 1 on all interfaces so that ssl can use "localhost" as destination + $ # Not sure if this is needed for ipv6 though $ sysctl -w net.ipv4.conf.default.route_localnet=1 $ sysctl -w net.ipv4.conf.all.route_localnet=1 $ # DROP martian packets as they would have been if route_localnet was zero $ # Note: packets not leaving the server aren't affected by this, thus sslh will still work - $ ip6tables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP - $ ip6tables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP + $ ip6tables -t raw -A PREROUTING ! -i lo -d ::1/128 -j DROP + $ ip6tables -t mangle -A POSTROUTING ! -o lo -s ::1/128 -j DROP $ # Mark all connections made by ssl for special treatment (here sslh is run as user "sslh") $ ip6tables -t nat -A OUTPUT -m owner --uid-owner sslh -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CONNMARK --set-xmark 0x01/0x0f @@ -273,7 +274,7 @@ Tranparent proxying with IPv6 is similarly set up as follows: $ # Configure routing for those marked packets $ ip -6 rule add fwmark 0x1 lookup 100 - $ ip -6 route add local 0.0.0.0/0 dev lo table 100 + $ ip -6 route add local ::/0 dev lo table 100 Explanation: To be able to use `localhost` as destination in your sslh config along with transparent proxying