{"id":3534,"date":"2016-09-05T14:41:03","date_gmt":"2016-09-05T12:41:03","guid":{"rendered":"https:\/\/adrhc.go.ro\/wordpress\/?p=3534"},"modified":"2017-10-13T09:30:20","modified_gmt":"2017-10-13T07:30:20","slug":"ssh-http-protocol-multiplexing","status":"publish","type":"post","link":"https:\/\/adrhc.go.ro\/blog\/ssh-http-protocol-multiplexing\/","title":{"rendered":"ssh, http and https multiplexing"},"content":{"rendered":"<pre class=\"brush:bash shell;gutter:true;toolbar:false\">\r\nThis is about how to have the ssh and http(s) server share the same port (e.g. 80 or 443 port).\r\nThis is really cool :).\r\n\r\n# Used sources:\r\n# http:\/\/yalis.fr\/cms\/index.php\/post\/2014\/02\/22\/Multiplex-SSH-and-HTTPS-on-a-single-port\r\n# http:\/\/blog.cppse.nl\/apache-proxytunnel-ssh-tunnel\r\n# http:\/\/serverfault.com\/questions\/355271\/ssh-over-https-with-proxytunnel-and-nginx\r\n# http:\/\/tyy.host-ed.me\/pluxml\/article4\/port-443-for-https-ssh-and-ssh-over-ssl-and-more\r\n# http:\/\/ipset.netfilter.org\/iptables.man.html\r\n# http:\/\/ipset.netfilter.org\/iptables-extensions.man.html\r\n# http:\/\/man7.org\/linux\/man-pages\/man8\/ip-rule.8.html\r\n# http:\/\/lartc.org\/howto\/lartc.netfilter.html\r\n# http:\/\/www.iana.org\/assignments\/service-names-port-numbers\/service-names-port-numbers.xhtml?search=Unassigned\r\n# https:\/\/cloud.githubusercontent.com\/assets\/2137369\/15272097\/77d1c09e-1a37-11e6-97ef-d9767035fc3e.png\r\n# http:\/\/www.adminsehow.com\/2011\/09\/iptables-packet-traverse-map\/\r\n\r\n### begin sshttp setup 1\r\n# https:\/\/github.com\/stealth\/sshttp\r\n# Below are the preparations for this setup:\r\n# sshttpd listens on 80 for ssh and http connections. It forwards to ssh:1022 and nginx:880.\r\n# Will work these:\r\nssh -p 1022 gigi@127.0.0.1\t\t-> access tried from within 192.168.1.31 host\r\nssh -p 1022 gigi@192.168.1.31\t-> access tried from within 192.168.1.31 host\r\nssh -p 80 gigi@adrhc.go.ro\t\t-> access tried from within 192.168.1.31 host or from internet\r\nhttp:\/\/127.0.0.1\/public\/\t\t-> access tried from within 192.168.1.31 host\r\nhttp:\/\/127.0.0.1:880\/public\/\t-> access tried from within 192.168.1.31 host\r\nhttp:\/\/192.168.1.31:880\/public\/\t-> access tried from within 192.168.1.31 host\r\nhttp:\/\/192.168.1.31\/public\/\t\t-> access tried from 192.168.1.31's LAN\r\nhttp:\/\/adrhc.go.ro\/public\/\t\t-> access tried from within 192.168.1.31 host or from internet\r\n# Won't work this:\r\nssh -p 1022 gigi@adrhc.go.ro\t-> access tried from within 192.168.1.31 host or from internet\r\nhttp:\/\/192.168.1.31\/public\/\t\t-> access tried from within 192.168.1.31 host\r\nhttp:\/\/adrhc.go.ro:880\/public\/\t-> access tried from within 192.168.1.31 host or from internet\r\n\r\n# \/etc\/modules\r\nmodprobe nf_conntrack_ipv4\r\nmodprobe nf_conntrack\r\necho \"nf_conntrack\" >> \/etc\/modules\r\necho \"nf_conntrack_ipv4\" >> \/etc\/modules\r\n\r\n# in \/etc\/ssh\/sshd_config make sure to have:\r\n# Port 1022\r\n# Banner \/etc\/sshd-banner.txt \r\n# Makefile uses the content of \/etc\/sshd-banner.txt, e.g.:\r\n# SSH_BANNER=-DSSH_BANNER=\\\"adrhc\\'s\\ SSH\\ server\\\"\r\ncat \/etc\/sshd-banner.txt\r\nadrhc's SSH server\r\n\r\n# configure nf-setup, e.g. for sshttpd.service below should be:\r\nDEV=\"eth0\"\r\nSSH_PORT=1022\r\n# HTTP_PORT=1443\r\nHTTP_PORT=880\r\n# also you could add this afterwards in order not to run nf-setup if already run:\r\nif [ \"`iptables -t mangle -L | grep -v -P \"^ufw-\" | grep -P \"^DIVERT.+tcp spt:$HTTP_PORT\"`\" != \"\" ]; then\r\n\techo \"sshttp netfilter rules already applied ...\"\r\n\texit 0\r\nfi\r\necho \"applying sshttp netfilter rules ...\"\r\n\r\n# for nginx or apache take care of address binding not to overlap with sshttpd.service, e.g.:\r\n#    server {\r\n#        listen\t127.0.0.1:80;\r\n#        listen\t127.0.0.1:880;\r\n#        # listen 192.168.1.31:80; -> used\/bound by sshttpd.service below\r\n#        listen\t192.168.1.31:880;\r\n\r\n# install the systemd sshttpd.service defined below:\r\nsudo chown root: \/etc\/systemd\/system\/sshttpd.service && sudo chmod 664 \/etc\/systemd\/system\/sshttpd.service && sudo systemctl daemon-reload; cp -v $HOME\/compile\/sshttp\/nf-setup $HOME\/apps\/bin\r\n\r\n# systemd sshttpd.service:\r\n[Unit]\r\n# see https:\/\/github.com\/stealth\/sshttp\r\nDescription=SSH\/HTTP(S) multiplexer\r\n# for any address binding conflict that occurs between ufw, ssh, nginx and sshttp I want ufw, ssh and nginx to win against sshttp\r\nAfter=network.target\r\n# sudo iptables -L | grep -v -P \"^ufw-\" | grep -P \"1022|1443|880|DIVERT|DROP|ssh\"\r\n# sudo iptables -t mangle -L | grep -v -P \"^ufw-\" | grep -P \"1022|1443|880|DIVERT|DROP|ssh\"\r\n[Service]\r\nType=forking\r\nRuntimeDirectory=sshttpd\r\nExecStartPre=-\/bin\/chown nobody: \/run\/sshttpd\r\nExecStartPre=-\/home\/gigi\/apps\/bin\/nf-setup\r\nRestart=on-failure\r\nRestartSec=3\r\nTimeoutStartSec=5\r\nTimeoutStopSec=5\r\n# using 443 for sshttpd:\r\n# ssh -p 443 gigi@adrhc.go.ro\r\n# wget --no-check-certificate https:\/\/adrhc.go.ro\/\r\n# ExecStart=\/home\/gigi\/apps\/bin\/sshttpd -n 4 -S 1022 -H 1443 -L 443 -l 192.168.1.31 -U nobody -R \/run\/sshttpd\r\n# using 80 for sshttpd:\r\n# ssh -p 80 gigi@adrhc.go.ro\r\n# wget http:\/\/adrhc.go.ro\/public\r\nExecStart=\/home\/gigi\/apps\/bin\/sshttpd -n 4 -S 1022 -H 880 -L 80 -l 192.168.1.31 -U nobody -R \/run\/sshttpd\r\n[Install]\r\nWantedBy=multi-user.target\r\n\r\n### begin sshttp setup 2 (read first sshttp step 1)\r\n# Below are the preparations for this setup:\r\n# sshttpd listens on 444 for ssh and https connections. \r\n# sshttpd forwards to ssh:1022 or stunnel:1443.\r\n# stunnel:1443 forwards to nginx:127.0.0.1:1080 or ssh:127.0.0.1:22 based on sni.\r\n# the original remote client's ip is accessible (only for https but not ssh) with $realip_remote_addr (http:\/\/nginx.org\/en\/docs\/http\/ngx_http_realip_module.html#real_ip_header)\r\n\r\n# Issue: any redirect (301 or 302) used in the server 127.0.0.1:1080 defined below will set Location header to http instead of https\r\n# - see sshttp setup 3 for a solution \r\n# - see https:\/\/forum.nginx.org\/read.php?2,269623,269647#msg-269647 (listen proxy_protocol and rewrite redirect scheme) for a better? solution:\r\nsrc\/http\/ngx_http_header_filter_module.c: \r\n#if (NGX_HTTP_SSL) \r\nif (c->ssl || port == 443) { \r\n*b->last++ ='s'; \r\n} \r\n#endif \r\n\r\n# Won't work Transmission remote GUI but the web page will still work.\r\n# ERROR (while using Transmission remote GUI):\r\n\t2016\/09\/19 15:03:42 [error] 5562#0: *2431 broken header: \"\u0016\u0003\u0001\u0001>\u0001\u0001:\u0003\u0003azX\ufffd\ufffd\ufffdg\ufffd\ufffd^}q\ufffd\u0002\/\ufffd\ufffd\ufffdA\u0014\ufffd\ufffdRp(\ufffd\ufffd\ufffdn3\ufffd\ufffd0\ufffd,\ufffd(\ufffd$\ufffd\u0014\ufffd\r\n\t\ufffd\ufffd\ufffd\ufffdkjih9876\ufffd\ufffd\ufffd\ufffd\ufffd2\ufffd.\ufffd*\ufffd&\ufffd\ufffd\ufffd=5\ufffd\ufffd\/\ufffd+\ufffd'\ufffd#\ufffd\u0013\ufffd\t\ufffd\ufffd\ufffd\ufffdg@?>3210\ufffd\ufffd\ufffd\ufffdEDCB\ufffd1\ufffd-\ufffd)\ufffd%\ufffd\ufffd\u0004\ufffd&lt;\/\ufffdA\ufffd\u0011\ufffd\ufffd\r\n\t\ufffd\u0003                                                                                      \ufffd\u0002\u0004\ufffd\u0012\u0016\u0013\u0010\r\n\t\ufffd\u0001g\r\n\t\t127.0.0.1\r\n\t\u001e\u0006\u0001\u0006\u0002\u0006\u0003\u0001\u0002\u0003\u0004\u0001\u0004\u0002\u0004\u0003\u0003\u0001\u0003\u0002\u0003\u0003\u0002\u0001\u0002\u0002\u0002\u0003\u0001\u0001\" while reading PROXY protocol, client: 127.0.0.1, server: 127.0.0.1:443\r\n\tN\u0001\u04feHu|\ufffd\u0003\ufffd\u001d\ufffd4|\ufffdsf\ufffd\ufffdQ\ufffdj$\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd0\ufffd,\ufffd(\ufffd$\ufffd\u0014\ufffd432 broken header: \"\u0016\u0003\u0001\u0001>\u0001\u0001:\u0003\u0003LM2V\r\n\t\ufffd\ufffd\ufffd\ufffdkjih9876\ufffd\ufffd\ufffd\ufffd\ufffd2\ufffd.\ufffd*\ufffd&\ufffd\ufffd\ufffd=5\ufffd\ufffd\/\ufffd+\ufffd'\ufffd#\ufffd\u0013\ufffd\t\ufffd\ufffd\ufffd\ufffdg@?>3210\ufffd\ufffd\ufffd\ufffdEDCB\ufffd1\ufffd-\ufffd)\ufffd%\ufffd\ufffd\u0004\ufffd&lt;\/\ufffdA\ufffd\u0011\ufffd\ufffd\r\n\t\ufffd\u0003                                                                                      \ufffd\u0002\u0004\ufffd\u0012\u0016\u0013\u0010\r\n\t\ufffd\u0001g\r\n\t\t127.0.0.1\r\n\t\u001e\u0006\u0001\u0006\u0002\u0006\u0003\u0001\u0002\u0003\u0004\u0001\u0004\u0002\u0004\u0003\u0003\u0001\u0003\u0002\u0003\u0003\u0002\u0001\u0002\u0002\u0002\u0003\u0001\u0001\" while reading PROXY protocol, client: 127.0.0.1, server: 127.0.0.1:443\r\n\r\n# in systemd sshttpd.service change to:\r\n# router: 443 -> 444 -> also make sure ufw allows 444\r\n# ssh -p 443 gigi@adrhc.go.ro\r\n# wget --no-check-certificate https:\/\/adrhc.go.ro\/\r\nExecStart=\/********\/apps\/bin\/sshttpd -n 4 -S 1022 -H 1443 -L 444 -l 192.168.1.31 -U nobody -R \/run\/sshttpd\r\n\r\n# in nginx add this \"magic\" server:\r\nserver {\r\n\tlisten 127.0.0.1:1080 default_server proxy_protocol;\r\n\tinclude xhttpd_1080_proxy.conf;\r\n\tport_in_redirect off;\r\n\t# change also fastcgi_params! (see below)\r\n\t... your stuff ...\r\n}\r\n\r\n# xhttpd_1080_proxy.conf:\r\nset_real_ip_from 192.168.1.0\/24;\r\nset_real_ip_from 127.0.0.0\/8;\r\n# set_real_ip_from ::1\/32; -> doesn't work for me\r\nreal_ip_header proxy_protocol;\r\nset $real_internet_https \"on\";\r\nset $real_internet_port \"443\";\r\n\r\n# in fastcgi_params have (besides your stuff):\r\n# This special fastcgi_params must be used only by \"magic server\" (127.0.0.1:1080)!\r\nfastcgi_param HTTPS $real_internet_https if_not_empty;\r\nfastcgi_param SERVER_PORT $real_internet_port if_not_empty;\r\n\r\n# stunnel.conf for server side\r\n# sudo killall stunnel; sleep 1; sudo bin\/stunnel etc\/stunnel\/stunnel.conf\r\npid = \/run\/stunnel.pid\r\ndebug = 4\r\noutput = \/********\/apps\/log\/stunnel.log\r\noptions = NO_SSLv2\r\ncompression = deflate\r\ncert = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-pub.pem\r\nkey = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-priv-no-pwd.pem\r\n[tls]\r\naccept = 192.168.1.31:1443\r\nconnect = 127.0.0.1:1080\r\nprotocol = proxy\r\n[ssh]\r\nsni = tls:tti.go.ro\r\nconnect = 127.0.0.1:22\r\nrenegotiation = no\r\ndebug = 5\r\ncert = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-pub.pem\r\nkey = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-priv-no-pwd.pem\r\n[www on any]\r\nsni = tls:*\r\nconnect = 127.0.0.1:1080\r\nprotocol = proxy\r\n\r\n# stunnel.conf for client side\r\n# killall stunnel; sleep 1; stunnel ****stunnel.conf && tailf ****stunnel.log\r\n# ssh -p 1194 gigi@localhost\r\npid = \/****************\/temp\/stunnel.pid\r\ndebug = 4\r\noutput = \/****************\/****stunnel.log\r\noptions = NO_SSLv2\r\n[tti.go.ro]\r\n# Set sTunnel to be in client mode (defaults to server)\r\nclient = yes  \r\n# Port to locally connect to\r\naccept = 127.0.0.1:1194  \r\n# Remote server for sTunnel to connect to\r\nconnect = adrhc.go.ro:443\r\nsni = tti.go.ro\r\nverify = 2\r\nCAfile = \/****************\/****Temp\/Zyxel\/adrhc.go.ro-server-pub.pem\r\n# checkHost = certificate's CN field (see \"Rejected by CERT at\" in stunnel.log for learning CN)\r\ncheckHost = adrhc.go.ro\r\n# CAfile = \/****************\/****Temp\/Zyxel\/adr-pub.pem\r\n# checkHost = adr\r\n\r\n### begin sshttp setup 3 (read first sshttp step 2)\r\n# any redirect (301 or 302) used in the server 127.0.0.1:1080 defined above will go to the https server\r\n# Issue: the original remote client's ip is not accessible (https or ssh)\r\n\r\n# you'll need the https nginx configuration for your site listening at least on 127.0.0.1:443\r\n# you no longer need the \"magic\" server defined above\r\n# How this works:\r\n# browser\/stunnel-client useing ssl -> sshttpd:443 -> stunnel[tls to http] using ssl -> stunnel[http to https]\r\n\r\n# stunnel.conf for server side\r\n# sudo killall stunnel; sleep 1; sudo bin\/stunnel etc\/stunnel\/stunnel.conf\r\npid = \/run\/stunnel.pid\r\ndebug = 4\r\noutput = \/********\/apps\/log\/stunnel.log\r\noptions = NO_SSLv2\r\ncompression = deflate\r\ncert = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-pub.pem\r\nkey = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-priv-no-pwd.pem\r\n[tls]\r\naccept = 192.168.1.31:1443\r\nconnect = 127.0.0.1:1081\r\nprotocol = proxy\r\n[ssh]\r\nsni = tls:tti.go.ro\r\nconnect = 127.0.0.1:22\r\nrenegotiation = no\r\ndebug = 5\r\ncert = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-pub.pem\r\nkey = \/********\/apps\/etc\/nginx\/certs\/adrhc.go.ro-server-priv-no-pwd.pem\r\n[tls to http]\r\nsni = tls:*\r\nconnect = 127.0.0.1:1081\r\n# connect = 127.0.0.1:1080\r\n# protocol = proxy\r\n[http to https]\r\naccept = 127.0.0.1:1081\r\nconnect = 127.0.0.1:443\r\nclient = yes\r\n\r\n### begin sslh setup\r\n# https:\/\/github.com\/yrutschle\/sslh\r\n# Here I use ssh:1021 instead of ssh:1022.\r\nsudo apt-get install sslh\r\n\r\nsudo useradd -d \/nonexistent -M -s \/bin\/false sslh\r\n# according to https:\/\/github.com\/yrutschle\/sslh#capabilities-support I need:\r\nsudo setcap cap_net_bind_service,cap_net_admin+pe \/usr\/sbin\/sslh-select\r\nsudo getcap -rv \/usr\/sbin\/sslh-select\r\n\r\ncat \/etc\/default\/sslh\r\nRUN=yes\r\nDAEMON=\/usr\/sbin\/sslh-select\r\n# with --transparent the local ip is not acceptable:\r\nDAEMON_OPTS=\"--transparent --timeout 1 --numeric --user sslh --listen 192.168.1.31:334 --ssh 192.168.1.31:1021 --http 192.168.1.31:80 --pidfile \/var\/run\/sslh\/sslh.pid\"\r\n# without --transparent is acceptable also local ip:\r\n# DAEMON_OPTS=\"--transparent --timeout 1 --numeric --user sslh --listen 192.168.1.31:334 --ssh 192.168.1.31:1021 --http 127.0.0.1:80 --pidfile \/var\/run\/sslh\/sslh.pid\"\r\n\r\ncat \/etc\/systemd\/system\/sslh.service.d\/custom.conf \r\n# cp -v $HOME\/bin\/systemd-services\/sslh-setup.sh $HOME\/apps\/bin\r\n[Service]\r\nExecStartPre=-\/********\/apps\/bin\/sslh-setup.sh\r\nExecStart=\r\nExecStart=\/usr\/sbin\/sslh-select --foreground $DAEMON_OPTS\r\nSuccessExitStatus=15\r\n\r\ncat sslh-setup.sh\r\n#!\/bin\/sh\r\nif [ \"`sudo iptables -t mangle -L | grep -P \"^SSLH\\s.+\\sspt:1021\"`\" != \"\" ]; then\r\n\techo \"SSLH netfilter rules already applied ...\"\r\n\texit 0\r\nfi\r\niptables -t mangle -N SSLH\r\niptables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 1021 --jump SSLH\r\niptables -t mangle -A OUTPUT --protocol tcp --out-interface eth0 --sport 80 --jump SSLH\r\niptables -t mangle -A SSLH --jump MARK --set-mark 0x1\r\niptables -t mangle -A SSLH --jump ACCEPT\r\nip rule add fwmark 0x1 lookup 100\r\nip route add local 0.0.0.0\/0 dev lo table 100\r\n\r\nsudo systemctl daemon-reload\r\nsudo systemctl enable sslh\r\nsudo systemctl start sslh\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This is about how to have the ssh and http(s) server share the same port (e.g. 80 or 443 port). This is really cool :). # Used sources: # http:\/\/yalis.fr\/cms\/index.php\/post\/2014\/02\/22\/Multiplex-SSH-and-HTTPS-on-a-single-port # http:\/\/blog.cppse.nl\/apache-proxytunnel-ssh-tunnel # http:\/\/serverfault.com\/questions\/355271\/ssh-over-https-with-proxytunnel-and-nginx # http:\/\/tyy.host-ed.me\/pluxml\/article4\/port-443-for-https-ssh-and-ssh-over-ssl-and-more # http:\/\/ipset.netfilter.org\/iptables.man.html # http:\/\/ipset.netfilter.org\/iptables-extensions.man.html [&hellip;]<\/p>\n<div class=\"link-more\"><a href=\"https:\/\/adrhc.go.ro\/blog\/ssh-http-protocol-multiplexing\/#more-3534\" class=\"more-link\">Continue reading &#10142; <span class=\"screen-reader-text\">ssh, http and https multiplexing<\/span><\/a><\/div>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,11,49,50],"tags":[40,166,42,167,98,99],"class_list":["post-3534","post","type-post","status-publish","format-standard","hentry","category-howto","category-linux","category-network","category-security","tag-firewall","tag-multiplex","tag-network","tag-ssh","tag-sshttp","tag-sslh"],"_links":{"self":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/3534","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/comments?post=3534"}],"version-history":[{"count":0,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/3534\/revisions"}],"wp:attachment":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/media?parent=3534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/categories?post=3534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/tags?post=3534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}