-
Notifications
You must be signed in to change notification settings - Fork 370
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sslh Incorrectly Identifies all Protocols as SSH #390
Comments
Hi, I am the author of the PR #388. The updated script really only does 2 things: looking for the '--transparent' flag and automatically configure the iptables / routing rules given in the example here (it is not enabled by default). From my limited understanding of the iptable rules, it seems that every outgoing connection to the various services made by sslh will marked, and response is intercepted and send back to sslh to be sent out from port 443. Thus, it is only possible for transparent mode to work only when the services are reachable via localhost. From your examples, it look to me that the transparent mode is not enabled (as '--transparent' flag is missing and the packets will be lost if you are using the hostname of the containers and nothing will work) and the bug is likely caused by something else. I have a similar setup to yours which i was able to get it working as follows: sslh:
build: https://github.com/klementng/sslh.git
container_name: system-sslh
environment:
- TZ=${TZ}
cap_add:
- NET_ADMIN
- NET_RAW
sysctls:
- net.ipv4.conf.default.route_localnet=1
- net.ipv4.conf.all.route_localnet=1
volumes:
- ./sslh:/config
command:
- '--transparent'
- '--config=/config/sslh.conf'
ports:
- 0.0.0.0:443:443
#- 0.0.0.0:443:443/udp
- 0.0.0.0:80:80 #nginx
- 0.0.0.0:8443:8443 # nginx
extra_hosts:
- localbox:host-gateway
restart: unless-stopped
nginx:
image: lscr.io/linuxserver/nginx:latest
container_name: system-nginx
environment:
- PUID=${PUID}
- PGID=${PGID}
- TZ=${TZ}
volumes:
- ./nginx:/config
- ./certbot:/certs
network_mode: service:sslh #### notice that nginx is using sslh container network. this makes nginx contactable by sslh using localhost
My sslh config: foreground: true;
transparent: true;
timeout: 3;
# Logging configuration
# Value: 1: stdout; 2: syslog; 3: stdout+syslog; 4: logfile; ...; 7: all
verbose-config: 7; # print configuration at startup
verbose-config-error: 7; # print configuration errors
verbose-connections: 7; # trace established incoming address to forward address
verbose-connections-error: 7; # connection errors
verbose-connections-try: 0; # connection attempts towards targets
verbose-fd: 0; # file descriptor activity, open/close/whatnot
verbose-packets: 0; # hexdump packets on which probing is done
verbose-probe-info: 7; # what's happening during the probe process
verbose-probe-error: 7; # failures and problems during probing
verbose-system-error: 7; # system call problem, i.e. malloc, fork, failing
verbose-int-error: 7; # internal errors, the kind that should never happen
logfile: "/config/sslh.log"
listen:
(
{ host: "0.0.0.0"; port: "443"; },
# { host: "0.0.0.0"; port: "443"; is_udp: true; },
);
protocols:
(
{ name: "tls"; host: "localhost"; port: "8443";},
{ name: "openvpn"; host: "localhost"; port: "1194";},
{ name: "ssh"; host: "localhost"; port: "22"; keepalive: true;},
{ name: "anyprot"; host: "localhost"; port: "8443";},
# { name: "wireguard"; host: "localbox"; port: "51820"; is_udp: true; transparent:false; fork: false},
# { name: "anyprot"; host: "localbox"; port: "51820"; is_udp: true; transparent:false; keepalive: true},
);
on-timeout: "tls";
As I could not attach my openvpn container to sslh (due to other networking requirements) i used the stream method in nginx to proxy my openvpn and ssh connections my nginx config stream{
server {
listen 22;
proxy_pass localbox:22;
}
server {
listen 1194;
proxy_pass localbox:1194;
}
} The above example could probably be removed if sslh networking is set to network_mode: host (the script will modify the host iptables / routing rules). I have tested it before but I decided to keep all my networking within docker. The only problem i faced is when using sslh for wireguard would cause the speed would drop all the way to <1mbps. which i just redirected port 443 udp to the wireguard port since it was the only udp service I have |
@klementng Thanks for responding and providing such detailed information!
I tried using the
I don't use a config file, as my setup uses the command line flags approach, but your setup looks very similar to what I tried but couldn't get to work.
Are you sure about this? Assuming I'm understanding it correctly, this seems to suggest otherwise. |
Yes I'm sure. The iptables rule that are automatically set are for 'transparent proxy to one host'. In order to proxy to multiple host as shown in the link, a different set of iptables rules must be set for all the container (i.e. the nginx container must have its own iptables rule to forward the traffic back to sslh container). This make everything very complicated and infeasible as likely not all images will have iptables installed, and rules must be manually set each time the container is recreated. Also I was able to reproduce the bug that you were facing which oddly only occurs with the cli. The bug magically went away when I manually deleted and re-set the iptables rules. After some investigating I have isolated the issue to be caused by ipv6 rules ( there were error printing out if it was not enabled, i figured it would be a non-issue but i guess not). I have created a patch that seemed to be working: sslh:
build: https://github.com/klementng/sslh.git#docker/transparent-patch sudo docker compose build sslh My docker compose config: sslh:
build: https://github.com/klementng/sslh.git#docker/transparent-patch
container_name: system-sslh
environment:
- TZ=${TZ}
cap_add:
- NET_ADMIN
- NET_RAW
sysctls:
- net.ipv4.conf.default.route_localnet=1
- net.ipv4.conf.all.route_localnet=1
volumes:
- ./sslh:/config
command:
- '--transparent'
- '--foreground'
- '--listen=0.0.0.0:443'
- '--openvpn=localhost:1194'
- '--http=localhost:80'
- '--tls=localhost:8443'
- '--ssh=localhost:22'
- '--verbose-probe-info=7'
- '--verbose-probe-error=7'
# - '--config=/config/sslh.conf'
networks:
default:
ipv4_address: 172.20.0.50
ports:
- 0.0.0.0:443:443 #sslh
- 0.0.0.0:80:80 #nginx http
restart: unless-stopped |
Ah okay. I understand now. Thanks for the explanation!
I see that your PR for the fix has been merged in. I have not had a chance to try it, but once I do, I'll let you know if I encounter any further issues with it. That said, I am still going to leave this ticket open since, as far as I know, the SSH issue that I am seeing has not been resolved. |
This is happening to me as well, only in docker. How can I fix that? Thanks! |
@paulhybryant which sslh versions? Try to to build from latest source too and test |
The latest one. This is my container configuration
I can confirm that the forwarding works, it is just not selecting the right protocol From the logs, I can see The first one is from curl, and the next is from git clone |
It seems that sslh is redirecting only to SSH because a timeout occurs.
From the code documentation, in case of a timeout and unless specified otherwise, Changing the above to:
solved the issue in my case. CPU usage went down to ~8%, SSH logins became noticeable faster and HTTPS was detected successfully. I have not (yet) tested with more protocols. |
This is a nice workaround to be aware of, but unfortunately, I am not sure that it is going to be useful for me since I use more than two protocols with |
I am using the sslh Docker container (the image's build date is 2023-07-30) to expose an NGINX server on http and https as well as an OpenVPN server on the same port. To do this, I use this command:
This setup works fine, but I also want to expose an SSH server. To try doing this, I have updated the command used by the container to this:
After making this change, I verified that SSH was accessible as intended, and it was, but unfortunately, this change has the undesirable side effect of causing traffic intended for HTTP, HTTPS, or OpenVPN to be incorrectly classified as SSH traffic. Effectively, the setup becomes no different than if I were exposing the SSH server directly.
I don't see why this would matter for my issue, but in case it does, the Docker container for sslh uses a bridge network through which I expose port 443 to the host system. The NGINX and OpenVPN servers each run in their own Docker containers and are connected to the same bridge network. sslh is configured to use the hostnames of the containers to hand off the requests to them. In the case of the SSH server, I want to make the host system's SSH server accessible. As I have said, making the SSH server accessible works fine, but comes at the cost of causing everything else to not work.
Ultimately, I want to eventually use a transparent configuration, but since I was unable to get a transparent configuration working with my setup even after #388 was merged, I have opted to leave that alone for now.
The text was updated successfully, but these errors were encountered: