Difference between revisions of "sslh"

From wiki
(Don't override system files)
(Fix stop command)
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Debian}}{{WIP}}
+
{{DISPLAYTITLE:sslh installation guide}}
sslh is a program that allows you to run several programs on port 443. Mainly it allows your [[SSH|SSH server]] and [[Nginx|web server]] to share the same port.
+
{{Debian}}[http://www.rutschle.net/tech/sslh.shtml sslh] is a program that allows you to run several programs on port 443. Mainly it allows your [[SSH|SSH server]] and [[Nginx|web server]] to share the same port.
  
{{Warning}}Using SSH can be a violation of your corporate internet use policy. Please act responsibly. In particular, '''never ever create a reverse tunnel''' from your company network. Also this tool is not disguising SHH traffic as web but simply changing the port and can be easily detected by your network administrator.
+
This guide will show how to install sslh in transparent mode with [[nftables]]. It will also use the lighter <code>sslh-select</code> instead of the simpler <code>sslh-fork</code>. For other modes of operation, refer to [https://github.com/yrutschle/sslh the documentation].
 +
 
 +
{{Warning|msg=}}Using SSH can be a violation of your corporate internet use policy. Please act responsibly. In particular, '''never ever create a reverse tunnel''' from your company network. Also this tool is not disguising SSH traffic as web but simply changing the port and can be easily detected by your network administrator.
 +
 
 +
== Prerequisite ==
 +
Before running this guide, you will need:
 +
* [[nftables]]
 +
* [[SSH]]
 +
* [[Nginx]]
  
 
== Install ==
 
== Install ==
 
<syntaxhighlight lang="console">
 
<syntaxhighlight lang="console">
# apt install sslh
+
$ sudo apt install sslh
 
</syntaxhighlight>When it ask you how sslh should be run, choose <code>standalone</code>.
 
</syntaxhighlight>When it ask you how sslh should be run, choose <code>standalone</code>.
  
 
== Configure ==
 
== Configure ==
sslh has several modes of operation. In this tutorial, we will use transparent mode without forks.  
+
sslh has several modes of operation. In this tutorial, we will use transparent mode with sslh-select.  
  
 
=== OpenSSH ===
 
=== OpenSSH ===
Line 28: Line 36:
  
 
=== Routing ===
 
=== Routing ===
Create file <code>/usr/local/sbin/sslh_network.sh</code>
+
Create file <code>/etc/nftables/sslh.conf</code>
 
<syntaxhighlight lang="shell">
 
<syntaxhighlight lang="shell">
#!/bin/sh
+
#!/usr/sbin/nft -f
  
iptables -w -t mangle -N SSLH
+
# Use ip as we want to configure sslh only for IPV4
iptables -w -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 2201 --jump SSLH
+
table ip sslh {
iptables -w -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 4433 --jump SSLH
+
        chain output {
iptables -w -t mangle -A SSLH --jump MARK --set-mark 0x1
+
                type route  hook output  priority -150;
iptables -w -t mangle -A SSLH --jump ACCEPT
+
                oif eth0 tcp sport { 2201, 4433 }  counter  mark set 0x4155;
ip rule add fwmark 0x1 lookup 100
+
        }
ip route add local 0.0.0.0/0 dev lo table 100
+
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Make it executable
+
and register it in <code>/etc/nftables.conf</code>
<syntaxhighlight lang="console">
+
<syntaxhighlight lang="sh">
# chmod +x /etc/sslh_network.sh
+
include "/etc/nftables/sslh.conf"
 
</syntaxhighlight>
 
</syntaxhighlight>
  
then create file <code>/etc/systemd/system/sslh_network.service</code>
+
and manually activate it with<syntaxhighlight lang="console">
<syntaxhighlight lang="ini">
+
$ sudo nft -f  /etc/nftables/sslh.conf
[Unit]
+
</syntaxhighlight>
Description=Set sslh network rules
 
After=network.target
 
  
 +
=== sslh ===
 +
Create file <code>/etc/systemd/system/sslh.service.d/override.conf</code> (you will have to create the folder)<syntaxhighlight lang="ini">
 
[Service]
 
[Service]
Type=oneshot
 
RemainAfterExit=yes
 
ExecStart=/usr/local/sbin/sslh_network.sh
 
  
[Install]
+
# Replace the start command and make it use sslh-select
WantedBy=multi-user.target
+
ExecStart=
</syntaxhighlight>
+
ExecStart=/usr/sbin/sslh-select --foreground $DAEMON_OPTS
 +
 
 +
# Run sslh as an user and use capabilities to bind ports
 +
User=sslh
 +
# Systemd 229
 +
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
 +
# Systemd 228 and bellow
 +
#SecureBits=keep-caps
 +
#Capabilities=cap_net_bind_service,cap_net_admin+pie
 +
 
 +
# Limit access
 +
PrivateTmp=true
 +
PrivateDevices=true
 +
ProtectSystem=full
 +
ProtectHome=true
  
enable it using
+
# Set routing rules automaticaly on script start
<syntaxhighlight lang="console">
+
PermissionsStartOnly=true
# systemctl enable sslh_network.service
 
Created symlink from /etc/systemd/system/multi-user.target.wants/sslh_network.service to /etc/systemd/system/sslh_network.service.
 
</syntaxhighlight>
 
  
and finally start it
+
# Check for mark 0x4155 (set by nftables) and forward packet to table 0x4155
<syntaxhighlight lang="console">
+
ExecStartPre=/sbin/ip rule add fwmark 0x4155 lookup 0x4155
# systemctl start sslh_network.service
+
ExecStopPost=/sbin/ip rule del fwmark 0x4155
</syntaxhighlight>
 
  
=== sslh ===
+
# Table 0x4155 to route all packets back to loopback interface
Create file <code>/etc/systemd/system/sslh.service.d/override.conf</code><syntaxhighlight lang="ini">
+
ExecStartPre=/sbin/ip route add local 0.0.0.0/0 dev lo table 0x4155
[Service]
+
ExecStopPost=/sbin/ip route del local 0.0.0.0/0 dev lo table 0x4155
ExecStart=
+
</syntaxhighlight>If using the <code>Capabilities=</code> rule for systemd 228-, you need to give the binary some capabilities as well<syntaxhighlight lang="console">
ExecStart=/usr/sbin/sslh-select --foreground $DAEMON_OPTS
+
$ sudo setcap cap_net_bind_service,cap_net_admin+ei /usr/sbin/sslh-select
 
</syntaxhighlight>Next edit file <code>/etc/default/sslh</code><syntaxhighlight lang="shell">
 
</syntaxhighlight>Next edit file <code>/etc/default/sslh</code><syntaxhighlight lang="shell">
 
# Default options for sslh initscript
 
# Default options for sslh initscript
Line 89: Line 104:
 
# and try to start sslh (standalone mode only)
 
# and try to start sslh (standalone mode only)
  
RUN=yes
+
RUN=no
  
 
# binary to use: forked (sslh) or single-thread (sslh-select) version
 
# binary to use: forked (sslh) or single-thread (sslh-select) version
 
# systemd users: don't forget to modify /lib/systemd/system/sslh.service
 
# systemd users: don't forget to modify /lib/systemd/system/sslh.service
DAEMON=/usr/sbin/sslh-select
+
DAEMON=/usr/sbin/sslh
  
DAEMON_OPTS="--user sslh -n --transparent --listen 203.0.113.23:443 --tls 203.0.113.23:4433 --ssh 203.0.113.23:2201 --pidfile /var/run/sslh/sslh.pid"
+
DAEMON_OPTS="-n --transparent --listen 203.0.113.23:443 --tls 203.0.113.23:4433 --ssh 203.0.113.23:2201"
</syntaxhighlight>Change done from the default are
+
</syntaxhighlight>Changes done from the default
* <code>RUN=yes</code> Activate the daemon
 
* <code>DAEMON=/usr/sbin/sslh-select</code> Use the no-fork version
 
 
* <code>-n</code> Don't resolve domain name of connecting ip in logs. This allow to not loose time doing a DNS lookup for each new client
 
* <code>-n</code> Don't resolve domain name of connecting ip in logs. This allow to not loose time doing a DNS lookup for each new client
 
* <code>--transparent</code> SSH and webserver will see connection as if it where coming directly from the outside. In particular, you will get the correct connecting IP address in the logs.
 
* <code>--transparent</code> SSH and webserver will see connection as if it where coming directly from the outside. In particular, you will get the correct connecting IP address in the logs.
Line 104: Line 117:
 
* <code>--tls 203.0.113.23:4433</code> IP and port of Nginx
 
* <code>--tls 203.0.113.23:4433</code> IP and port of Nginx
 
* <code>--ssh 203.0.113.23:2201</code> IP and port of OpenSSH
 
* <code>--ssh 203.0.113.23:2201</code> IP and port of OpenSSH
 +
* Remove <code>--user</code> option. The modification in the systemd script make it run with the correct user from the start.
 +
* Remove <code>--pidfile</code> option. It is useless with systemd.
  
 
=== Start ===
 
=== Start ===
 
You can now restart Nginx and start sslh<syntaxhighlight lang="console">
 
You can now restart Nginx and start sslh<syntaxhighlight lang="console">
# systemctl reload nginx && systemctl start sslh
+
$ sudo systemctl reload nginx && systemctl start sslh
 
</syntaxhighlight>
 
</syntaxhighlight>
 
[[Category:Linux Server]]
 
[[Category:Linux Server]]

Latest revision as of 08:50, 5 September 2020


Warning Warning: These instructions were only tested on Debian. It will probably work for other Linux distributions, but you might need to adapt the provided instructions.

sslh is a program that allows you to run several programs on port 443. Mainly it allows your SSH server and web server to share the same port.

This guide will show how to install sslh in transparent mode with nftables. It will also use the lighter sslh-select instead of the simpler sslh-fork. For other modes of operation, refer to the documentation.


Warning Warning: Using SSH can be a violation of your corporate internet use policy. Please act responsibly. In particular, never ever create a reverse tunnel from your company network. Also this tool is not disguising SSH traffic as web but simply changing the port and can be easily detected by your network administrator.

Prerequisite

Before running this guide, you will need:

Install

$ sudo apt install sslh

When it ask you how sslh should be run, choose standalone.

Configure

sslh has several modes of operation. In this tutorial, we will use transparent mode with sslh-select.

OpenSSH

We will start by configuring OpenSSH to listen on a second port. We do that by modifying /etc/ssh/ssd_config

# What ports, IPs and protocols we listen for
Port 2200
# Use these options to restrict which interfaces/protocols sshd will bind to
ListenAddress 203.0.113.23:2200 # direct access
ListenAddress 203.0.113.23:2201 # access through sslh

You can now restart your SSH server.

Nginx

Now we will need to free port 443 so that it can be used by sslh. Edit file /etc/nginx/snippets/listen-https.conf and change the port for IPV4

listen [2001:db8:3:47d0::2e:7]:443 ssl spdy;
listen 203.0.113.23:4433 ssl spdy;

Do not restart Nginx yet.

Routing

Create file /etc/nftables/sslh.conf

#!/usr/sbin/nft -f

# Use ip as we want to configure sslh only for IPV4
table ip sslh {
        chain output {
                type route  hook output  priority -150;
                oif eth0  tcp sport { 2201, 4433 }  counter  mark set 0x4155;
        }
}

and register it in /etc/nftables.conf

include "/etc/nftables/sslh.conf"

and manually activate it with

$ sudo nft -f  /etc/nftables/sslh.conf

sslh

Create file /etc/systemd/system/sslh.service.d/override.conf (you will have to create the folder)

[Service]

# Replace the start command and make it use sslh-select 
ExecStart=
ExecStart=/usr/sbin/sslh-select --foreground $DAEMON_OPTS

# Run sslh as an user and use capabilities to bind ports
User=sslh
# Systemd 229
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
# Systemd 228 and bellow
#SecureBits=keep-caps
#Capabilities=cap_net_bind_service,cap_net_admin+pie

# Limit access
PrivateTmp=true
PrivateDevices=true
ProtectSystem=full
ProtectHome=true

# Set routing rules automaticaly on script start
PermissionsStartOnly=true

# Check for mark 0x4155 (set by nftables) and forward packet to table 0x4155
ExecStartPre=/sbin/ip rule add fwmark 0x4155 lookup 0x4155
ExecStopPost=/sbin/ip rule del fwmark 0x4155

# Table 0x4155 to route all packets back to loopback interface
ExecStartPre=/sbin/ip route add local 0.0.0.0/0 dev lo table 0x4155
ExecStopPost=/sbin/ip route del local 0.0.0.0/0 dev lo table 0x4155

If using the Capabilities= rule for systemd 228-, you need to give the binary some capabilities as well

$ sudo setcap cap_net_bind_service,cap_net_admin+ei /usr/sbin/sslh-select

Next edit file /etc/default/sslh

# Default options for sslh initscript
# sourced by /etc/init.d/sslh

# Disabled by default, to force yourself
# to read the configuration:
# - /usr/share/doc/sslh/README.Debian (quick start)
# - /usr/share/doc/sslh/README, at "Configuration" section
# - sslh(8) via "man sslh" for more configuration details.
# Once configuration ready, you *must* set RUN to yes here
# and try to start sslh (standalone mode only)

RUN=no

# binary to use: forked (sslh) or single-thread (sslh-select) version
# systemd users: don't forget to modify /lib/systemd/system/sslh.service
DAEMON=/usr/sbin/sslh

DAEMON_OPTS="-n --transparent --listen 203.0.113.23:443 --tls 203.0.113.23:4433 --ssh 203.0.113.23:2201"

Changes done from the default

  • -n Don't resolve domain name of connecting ip in logs. This allow to not loose time doing a DNS lookup for each new client
  • --transparent SSH and webserver will see connection as if it where coming directly from the outside. In particular, you will get the correct connecting IP address in the logs.
  • --listen 203.0.113.23:443 IP and port sslh listen to
  • --tls 203.0.113.23:4433 IP and port of Nginx
  • --ssh 203.0.113.23:2201 IP and port of OpenSSH
  • Remove --user option. The modification in the systemd script make it run with the correct user from the start.
  • Remove --pidfile option. It is useless with systemd.

Start

You can now restart Nginx and start sslh

$ sudo systemctl reload nginx && systemctl start sslh