Search code examples
sshtunneltunneling

HTTP reverse tunnel


Question

Is it possible to use a socks tunnel (or any other form of tunnel on port 80 or 443) to control the local machine that is creating the tunnel from the remote machine? Basically, a ssh -R [...] when ssh is not an option and only TCP connection on port 80 and 443 are possible?

Concrete scenario

Due to a very restrictive security policy of one of our customers, we currently have to connect to a Windows jump host without the ability to copy-and-paste stuff there. From there, we download needed files via web browser and copy via ssh to the target machine, or use ssh directly to do maintenance work on the target machine. However, this workflow is time-consuming, and honestly quite annoying.

Unfortunately, the firewall seems to be able to distinguish between real HTTP traffic and ssh as opening instructing sshd on our server to accept connections on 443 did not work.

Firewall
(HTTP only)
┌──────────────┐
│              │
│  ┌─────────┐ │ ???    ┌──────────┐
│  │Jumphost ├─┼───────►│Our Server│
│  │(Windows)│ │        └───▲──────┘
│  └──┬──────┘ │            │
│     │ssh     │            │ssh
│     │        │            │
│   ┌─▼─────┐  │        ┌───┴─────┐
│   │Target │  │        │Developer│
│   │(Linux)│  │        │Machine  │
│   └───────┘  │        └─────────┘
│              │
└──────────────┘

Any hints are highly appreciated 👍🏻


Solution

  • The problem seems to be a firewall with deep packet inspection.

    You can overcome it with using ssh over ssl, using stunnel or openssl.
    From the windows box you can tunnel with a stunnel client to our-server stunnel server.
    That encapsulate all (ssh) data into ssl therefore there is no difference to a HTTPS connection.

    Another option could be ptunnel-ng, it supports a tcp connection over ICMP (ping).

    Most firewalls ignores ICMP, if you can ping your our-server this should work, too.
    But ptunnel-ng seems sometimes a bit unstable.

    If you can't install/execute programs on the windows jumbBox, you can open ports, redirect them by ssh and use them directly by the target-linux.

    On your windows jumpbox:

    ssh target -R target:7070:our-server:443
    

    On the target (linux) you can use localhost:7070 to connect to our-server:443

    I would recommend to use docker for the client and server parts.
    I only can't use the ptunnel server inside a container, probably because of the required privileges.

    Using ptunnel

    On the server

    The ptunnel binary is build inside docker, but used by the host directly
    This sample expects an ubuntu server

    Dockerfile.server

    FROM ubuntu:latest
    ARG DEBIAN_FRONTEND=noninteractive
    RUN apt-get update && apt-get install -y build-essential autoconf automake git
    RUN mkdir -p /workdir
    WORKDIR /workdir
    RUN git clone https://github.com/lnslbrty/ptunnel-ng.git && cd ptunnel-ng && ./autogen.sh
    

    start-server.sh

    #!/bin/sh
    # Starts the icmp tunnel server, this doesn't work inside a docker container
    # Or perhaps it works, but I dont't know how
    script_dir=$(cd "$(dirname "$0")"; pwd)
    if [ ! -f $script_dir/ptunnel-ng ]; then
      # Build the ptunnel binary and copy it to the host
      docker build -t ptunnel-ng-build-server -f $script_dir/Dockerfile.server $script_dir
      docker run --rm -v $script_dir:/shared ptunnel-ng-build-server cp /workdir/ptunnel-ng/src/ptunnel-ng /shared
    fi
    
    magic=${1-123456}
    sudo $script_dir/ptunnel-ng --magic $magic
    

    On the client

    FROM alpine:latest as builder
    ARG DEBIAN_FRONTEND=noninteractive
    RUN apk add --update alpine-sdk bash autoconf automake git
    RUN mkdir -p /workdir
    WORKDIR /workdir 
    RUN git clone https://github.com/lnslbrty/ptunnel-ng.git && cd ptunnel-ng && ./autogen.sh
    
    FROM alpine:latest
    WORKDIR /workdir 
    COPY --from=builder /workdir/ptunnel-ng/src/ptunnel-ng .
    

    start-client.sh

    #!/bin/sh
    
    image=ptunnel-ng
    if ! docker inspect $image > /dev/null 2> /dev/null; then
      docker build -t $image .
    fi
    
    magic=${1-123456}
    ptunnel_host=${2-myserver.de}
    port=${3-2001}
    
    docker run --rm --detach -ti --name 'ptunnel1' -v $PWD:/shared -p 2222:2222 $image //workdir/ptunnel-ng --magic ${magic} -p${ptunnel_host} -l${port}
    

    If you try to run the ptunnel client on termux, this can be done, but requires some small code changes