Git Product home page Git Product logo

sshttp's Introduction

sshttp - hiding SSH servers behind HTTP

0. Intro

In case your FW policy forbids SSH access to the DMZ or internal network from outside, but you still want to use ssh on machines which only have one open port, e.g. HTTP, you can use sshttpd.

sshttpd can multiplex the following protocol pairs:

  • SSH/HTTP
  • SSH/HTTPS
  • SSH/SMTP (without SMTP multiline banners)
  • HTTPS SNI multiplexing
  • SSH/HTTPS with SNI multiplexing

1. Build

Be sure you run recent Linux kernel and install nf-conntrack as well as libcap and libcap-devel if you want to use the capability feature. On older systems the nf-conntrack module is named nf-conntrack-ipv4.

Inside src dir:

$ make

There is a new splice branch inside the git. git checkout splice before make, if you want to test this new branch. It implements zero-copy in terms of the splice(2) system call which has a performance benefit since it avoids copying the network data between user and kernel land back and forth (read()/write()), which could also just be spliced kernel-internally at the "extra cost" of two additional pipe descriptors per connection.

proudly sponsored by:

2. Setup for single host

This paragraph describes the setup where all services run on the same host as sshttpd itself. The muxing happens to the same IP/IP6 address that the outside connects arrive to, so basically just the ports are changing per detected service.

sshttpd is an easy to use OSI-Layer5 switching daemon. It runs transparently on HTTP(S) port (-L switch, default 80) and decides on incoming connections whether this is SSH or HTTP(S) traffic. If its HTTP(S) traffic, it switches the traffic to the HTTP_PORT (-H, default 8080) and if its SSH traffic to SSH_PORT (-S, default 22) respectively.

After the build it is time to pick the right netfilter script for setting up the fw rules. In iptables directory you will find the old style iptables version and in nft the new version for nft (but currently only using the compat layer).

You need to edit nf-setup script (nf6-setupif using IPv6) to match your network device and $PORTS (22 and 8080 are just fine for the SSH/HTTP case) and run it to install the proxy rules. Your sshd has to run on $SSH_PORT and your webserver on $HTTP_PORT. Thats basically it. Go ahead and run sshttpd (as root) and it will layer5-switch your traffic destinated to TCP port 80:

Take care when running nf-setup on a remote host in an SSH session - it will firewall port 22

# ./nf-setup
Using network device eth0
Setting up port 22 ...
Setting up port 8080 ...
# ./sshttpd -S 22 -L 80 -H 8080 -U nobody -R /var/empty
sshttpd: Using HTTP_PORT=8080 SSH_PORT=22 and local port=80. Going background. Using caps/chroot.
#

If you want to mux SMTP with sshttpd, just give 25 as -L parameter, 2525 as -H parameter, and setup your smtp daemon to listen on 2525. Then edit the nf-setup script to match these ports. In the Makefile, change the SMTP_DOMAIN and SSH_BANNER to your needs (SSH_BANNER must match exactly yours of the running sshd). SMTP/SSH muxing was tested with OpenSSH client and Postfix client and server.

When muxing IPv6 connections, the setup is basically the same; just use the nf6-setup script and invoke sshttpd with -6.

3. Transparent proxy setup

You can run sshttpd also on your gateway machine and transparently proxy/mux all of your HTTP(S)/SSH traffic to your internal LAN. To do so, run sshttpd with -T and use nf-tproxy rather than nf-setup as a template for your FW setup. Carefully read nf-tproxy so you don't lock yourself out of the network and all the network devices and IP addresses match your setup.

4. SNI Mux

With sshttpd you can also mux based on the HTTPS SNI. Just set up your nf-setup to contain the SNI ports (there are already samples) and invoke sshttpd with -N name:port e.g. sshttpd -S 22 -H 4433 -L 443 -N drops.v2:7350 to hide a sshd on 22 and a drops setup on port 7350 behind port 443, and at the same time serving your webserver from port 4433 to be visible to outside on port 443. This works because drops sets the SNI of drops.v2 in outgoing connects. Multiple -N switches are allowed so you could mux a lot of services via SNI. The ports/services must run all on the same machine where the original request was destinated to. If you just want to mux based on SNI, you can set the SSH port to 0 via -S 0.

5. Misc

You don't need to patch any of your ssh/web/smtp client or server software. It works as is. sshttpd runs only on Linux and needs IP_TRANSPARENT support. It would work without, but by using IP_TRANSPARENT it is possible to even have unmodified syslogs, e.g. the original source IP/port of incoming connections is passed as-is to the SSH/HTTP/SMTP servers.

Make sure the nf_conntrack and nf_conntrack_ipv4 or nf_conntrack_ipv6 modules are loaded. sshttpd is also a tricky anti-SSH0day (if ever:) and anti SSH-scanning/bruteforcing measurement. sshttpd has small footprint and was optimized for speed so it also runs on heavily loaded web servers.

Since version 0.24, sshttpd also supports multiple CPU cores. Unless -n 1 is used as switch, sshttpd binds one thread per CPU core, to better exploit the hardware if running on heavily used web servers. It still runs this fixed number of threads no matter how many 1000s connection it handles at the same time. sshttpd runs as nobody user inside a chroot() (configurable via -U and -R switch) if compiled with USE_CAPS. It can also distinguish between SSH and SSL sessions, you just have to use an LOCAL_PORT (-L) of 443 or 4433 and change the HTTP_PORT in the nf-setup script to match your webservers HTTPS port. You cannot mix HTTP/SSH and HTTPS/SSH in one sshttpd instance but you can run two sshttpd's to reach that goal: one on LOCAL_PORT 80 and one on LOCAL_PORT 443.

6. Alternative docu

As per 2017 it seems you have to provide alternative facts for everything, so here are some good writeups from other people for better understanding or in case my description was too brief:

sshttp's People

Contributors

jackric avatar stealth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sshttp's Issues

sshttp with pppoe

Hi, I'm trying to use sshttp with pppoe (mtu=1492, pppoe over eth0) e.g.:
sshttpd -n 4 -S 1022 -H 1443 -L 443 -l ${ppp0_ip} -U nobody -R /run/sshttpd
with my equivalent nf-setup using DEV=ppp0 instead of eth0 and 1022, 1443 ports I get the following behaviour:

  • websites visited from browser hang
  • ssh username@ppp0_ip hangs

When using this setup directly with eth0 (behind a router which connects to same ISP using same pppoe configuration + mtu=1500) everything works as expected (ssh username@eth0_ip, websites are accessible).

The exact mtu=1492 for ppp0 is mandatory otherwise no website works - found after many painful tests.
When using pppoe I bind sshd to ppp0_ip:1022 and nginx to ppp0_ip:1443 while when using eth0 directly I bind them to eth0_ip:1022 and eth0_ip:1443.

I guess sshttpd binary has nothing to do with the problem but only the iptables used by nf-setup; may be those iptables change/reset the mtu to 1500 -> I guess this might be because the result seems very similar to when used mtu 1500 with pppoe (websites hang).

So is this a bug or not?

sshttpd[2818]: sshttp::loop::NS_Socket::dstaddr::getsockopt:Protocol not available

  1. On trying to connect over https towards port 1081 that my sshttpd is listening to, /var/log/messages shows me this failure. I've built sshttpd from master branch.
    linux kernel 4.10.10

  2. I was surprised to see some random ip address in netstat
    tcp 0 0 192.168.1.5:1081 123.152.106.180:57183 SYN_RECV
    Would iptables the way to block this 123.152.106.180 entirely?

Add a license

I'm in the process of packaging sshttp for archlinux and by default our PKGBUILDS require a license. Would it be possible to specify under which license you would like to distribute sshttp?

getsockopt: No such file or directory

Im running into an issue with an error similar to the getsockopt error in #15

I'm running ssh on 2222 and http on 2280.

strace shows the following when I try to curl http://localhost:443:

[pid 13398] <... poll resumed>)         = 1 ([{fd=4, revents=POLLIN}])
[pid 13397] <... poll resumed>)         = 1 ([{fd=4, revents=POLLIN}])
[pid 13396] <... poll resumed>)         = 1 ([{fd=4, revents=POLLIN}])
[pid 13395] <... poll resumed>)         = 1 ([{fd=4, revents=POLLIN}])
[pid 13398] accept4(4,  <unfinished ...>
[pid 13397] accept4(4,  <unfinished ...>
[pid 13398] <... accept4 resumed>{sa_family=AF_INET, sin_port=htons(56942), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_NONBLOCK) = 5
[pid 13397] <... accept4 resumed>0x7ffe16a25040, [16], SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
[pid 13396] accept4(4,  <unfinished ...>
[pid 13395] accept4(4,  <unfinished ...>
[pid 13398] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4 <unfinished ...>
[pid 13397] poll([{fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=4, events=POLLIN|POLLOUT}], 5, 1000 <unfinished ...>
[pid 13398] <... setsockopt resumed>)   = 0
[pid 13396] <... accept4 resumed>0x7ffe16a25040, [16], SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
[pid 13395] <... accept4 resumed>0x7ffe16a25040, [16], SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
[pid 13398] accept4(4,  <unfinished ...>
[pid 13396] poll([{fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=4, events=POLLIN|POLLOUT}], 5, 1000 <unfinished ...>
[pid 13398] <... accept4 resumed>0x7ffe16a25040, [16], SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
[pid 13395] poll([{fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=4, events=POLLIN|POLLOUT}], 5, 1000 <unfinished ...>
[pid 13398] poll([{fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=4, events=POLLIN|POLLOUT}, {fd=5, events=POLLIN}], 6, 1000) = 1 ([{fd=5, revents=POLLIN}])
[pid 13398] getsockopt(5, SOL_IP, 0x50 /* IP_??? */, 0x7ffe16a25050, [16]) = -1 ENOENT (No such file or directory)
[pid 13398] close(5)                    = 0
[pid 13398] getpid()                    = 13398
[pid 13398] sendto(3, "<27>Apr 16 18:11:51 sshttpd[1339"..., 106, MSG_NOSIGNAL, NULL, 0) = 106

The log shows: sshttpd[14112]: sshttp::loop::NS_Socket::dstaddr::getsockopt:No such file or directory

my PORTS is set to "2222 2280" and I'm running $sudo ./sshttpd -S 2222 -L 443 -H 2280 -U nobody -R /var/empty.
I hope i just missed something simple in the documentation, I don't really understand what exactly s breaking.

The nf-setup output:

 $sudo ./nf-setup
[sudo] password for a:
modprobe: FATAL: Module nf_conntrack_ipv4 not found in directory /lib/modules/6.0.0-12parrot1-amd64
iptables: Chain already exists.
Using network device enp1s0
Setting up port 2222 ...
Setting up port 2280 ...
RTNETLINK answers: File exists

conntrack is loaded:

 $lsmod | grep conntrack
nf_conntrack          188416  2 nf_nat,xt_REDIRECT
nf_defrag_ipv6         24576  2 nf_conntrack,xt_socket
nf_defrag_ipv4         16384  2 nf_conntrack,xt_socket
libcrc32c              16384  6 nf_conntrack,nf_nat,btrfs,nf_tables,xfs,raid456

iptables has the rules:

$sudo iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i enp1s0 -p tcp -m tcp --dport 2222 -j DROP
-A INPUT -i enp1s0 -p tcp -m tcp --dport 2280 -j DROP
$sudo iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
 $sudo iptables -S -t raw
-P PREROUTING ACCEPT
-P OUTPUT ACCEPT
 $sudo iptables -S -t mangle
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DIVERT
-A PREROUTING -p tcp -m socket -j DIVERT
-A OUTPUT -o enp1s0 -p tcp -m tcp --sport 2222 -j DIVERT
-A OUTPUT -o enp1s0 -p tcp -m tcp --sport 2280 -j DIVERT
-A DIVERT -j MARK --set-xmark 0x1/0xffffffff
-A DIVERT -j ACCEPT

bind_local::bind ... address already in use

I have sucessfully configure sshttp over port 80.
http and ssh are working.

I am getting a lot of errors like this:

bind_local::bind ... address already in use

it is flooding my syslog. What could be the cause?

Trying to compile sshttp in ubuntu 16.04, fatal errors

I recently tried To install sshttp on my ubuntu server, I can clone it to the server, however when I try to run make

I receive the following error

root@seanhalephotos:/usr/local/src/sshttp# sudo make

c++ -c -O2 -Wall -std=c++11 -pedantic -DUSE_CAPS -DLINUX26 main.cc

main.cc:52:28: fatal error: sys/capability.h: No such file or directory

compilation terminated.

Makefile:44: recipe for target 'main.o' failed

make: *** [main.o] Error 1

Not sure where to go from that

Connection reset while detecting protocol.

hello,
I am experiencing similar problems as described here:
#11

If I run SSHTTP without binding a particular address just a port I get the following error. (curl localhost:2280 or ssh me@localhost -p 2280)

sshttp:: loop::NS_Socket::bind_local::bind:Address already in use

If I run it with localhost:14080 localhost:228 I get the following error. (curl localhost:2280 or ssh me@localhost -p 2280)

sshttp:: loop: Connection reset while detecting protocol.

Maybe I am missing something obvious, I am not an expert in networks. Any help is appreciated.

Problems running sshttp

I'm trying to run this on a rasp pi.
I downloaded project,
modified nf-setup with
SSH_PORT=22
HTTP_PORT=4433
ran make
then if I run ./sshttpd -L 443
I get

sshttpd: Using HTTP_PORT=8080 SSH_PORT=22 and local port=443. Going background.
Using caps/chroot.
NS_Socket::bind_local::bind:Permission denied

and if I use sudo I get

sshttpd: Using HTTP_PORT=8080 SSH_PORT=22 and local port=443. Going background.
Using caps/chroot.
chroot: No such file or directory
chroot: No such file or directory

I also tried using authbind instead of sudo and I get

sshttpd: Using HTTP_PORT=8080 SSH_PORT=22 and local port=443. Going background.
Using caps/chroot.
Operation not permitted

Anyone able to help with this? Thanks

cpu reachs 100%

Hi !

I'm experiencing 100% usage of cpu by sshttp process (debian7 - kernel 4.1.16-v7+ armv7l raspberry pi2 900mhz cpu). It happens when i stream media over https (sshttp routing).

How can i debug it or increment the type of logging ?

Thanks.
Sergio.

iptables: No chain/target/match by that name

Hello Sebastian,

There is a lot of information here but I would be very grateful if you could help me debug !

I am trying to install sshttp on my Raspberry Pi 3 running Raspbian.
Kernel information:
Linux raspbianpi 4.14.34-v7+ #1110 SMP Mon Apr 16 15:18:51 BST 2018 armv7l GNU/Linux

My aim is to deliver https/ssh traffic to my routers external port 443 with sshttp listening on router internal port 444 and then send ssh traffic to port 1022 and https traffic to port 443 in my LAN.

In my nf-setup and nf6-setup scripts I have this line at the top:
PORTS="1022 443 7350"
Is that correct? Do I need to include the port 7350?

I am following this guide by theYinYeti:
http://yalis.fr/cms/index.php/post/2014/02/22/Multiplex-SSH-and-HTTPS-on-a-single-port

I ran into some trouble make'ing the daemon.. libcap wasn't available only libcap2 which I used. I'm not sure if that would be a problem? Also I was unable to load the nf_tproxy_core module and it is not in my distribution apt-get at all. I downloaded the headers and sources from the latest Raspbian Kernel but nf_tproxy_core is not in there at all. Is it deprecated by now maybe?

I did manage to make the daemon but when I run it I get the error:

"iptables: No chain/target/match by that name"

... which happens when the nf-setup script tries to run this command:
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT

Here is the output of the last two times I tried to start the daemon using theYinYeti init script. It is taken from the output of the command: # grep 'sshttp' /var/log/daemon.log
image

By the way at 23:39:00 there is an unusual error with process sshttpd...
sshttpd[1778]: sshttp::loop::NS_Socket::dstaddr::getsockopt:No such file or directory

In my init file I named the daemon sshttp (not sshttpd) and I thought it had already exited with an error at 23:11:16 and this was a few minutes before I tried starting it again at 23:59:28.

And this is the error output from systemctl:
image

I try to start the daemon as root user (sudo su). Here is the output of running the command:
# strace -o /home/pi/strace_op1 /etc/init.d/sshttp start
strace_op1.txt

This is the script I run before everytime I try to start sshttp. It clears all rules and chains in iptables:
init_fw.sh.txt

Here is the output of the command # iptables-save > /home/pi/iptables_bckp2
This is what iptables looks like after sshttp fails to start:
iptables_bckp2.txt

Here are all the modules that are loaded:
loadedmodules.txt

I double checked the permissions and ownership of the daemon and init files and they are as per theYinYeti setup advice.
image

By the way this page https://blog.stalkr.net/2012/02/sshhttps-multiplexing-with-sshttp.html sets up a dedicated user for the daemon... I left it as 'nobody' in my config.

Do you think this because I never loaded the nf_tproxy_core module?

If so, does this mean I won't be able to use sshttp on my Pi or is there some way to compile/make the nf_tproxy_core module for my system?

Thank you,

Flex

sshttp can't open connection to the real server

I've installed sshttps following the instructions at http://blog.stalkr.net/2012/02/sshhttps-multiplexing-with-sshttp.html with only minor changes but somehow it doesn't seem to work for me. Here what happens if I try to connect from another machine:

% openssl s_client -connect $myhost:443
CONNECTED(00000003)
... long delay ...
26536:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:188:
% ssh -o Port=443 $myhost
... long delay ...
ssh_exchange_identification: Connection closed by remote host

On the server end ($myhost) lsof shows that sshttp doesn't manage to open connection to the real server:

COMMAND   PID    USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
...
sshttps 29812 sshttps    5u  IPv4            5319267      0t0     TCP $myhost:https->$myclient:39773 (ESTABLISHED)
sshttps 29812 sshttps    6u  IPv4            5319269      0t0     TCP $myclient:39773->$myhost:$SSH_PORT (SYN_SENT)

So there is probably something wrong with my iptables rules but I don't see what, any idea about what could be causing this? Or how could I debug this further?

Thanks in advance!

sshttp uses a lot of resources

I'm running sshttp on Ubuntu 14.04.1, multiplexing to HTTPS and SSH. When I initiate a download on HTTPS, an sshttpd thread immediately jumps to 100% CPU utilisation on one thread, limiting download speed to 1MB/s on an i7-620M processor.

Is this normal, or did I do anything wrong? Is there any way to improve performance?

Domain Fronting?

Is it possible to use sshttp with cloudfront or other providers for domain fronting?
It would be pretty rad to have "https traffic flowing to a0.awsstatic.com", that is domain fronted to another front end, like an ec2 or digital ocean image, and have the traffic be ssh.

Because at that point, you could tunnel ssh ports over that link and do c2 and exfil comms over "amazons front end".

mid-function includes break compile on Ubuntu 16.04

Basically you are doing #include <linux/netfilter_ipv4.h> right in the middle of int dstaddr(int sock, sockaddr *dst, socklen_t dlen) and the compiler does not seem happy about it.

In file included from socket.cc:131:
swab.h: In function 'int NS_Socket::dstaddr(int, sockaddr*, socklen_t)':
swab.h:8:1: error: a function-definition is not allowed here before '{' token

Does not work at all under unpriveleged LXC

Chroot and setrlimit is not permitted.
After removing chroot and serrlimit calls it hangs on first incoming connection.
Debugging is very hard because i cannot disable detaching from terminal

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.