From charlesreid1

Wifi Pod Overview

Services

UGR wifi pod ships the following services in Docker containers:

  • stunnel server
  • web server (hello world, report, file management)
  • https web server 9hello world)
  • mongodb database

Stretch goals:

  • Data to inform the server about processes that are running? How to install a program that runs on the pi and tries to call home and send updates on information going on with the operating system, running processes, etc.?

Please make a note:

  • The UGR wifi pod does not receive or process raw packet data. The Raspberry Pi device will extract network data, either by using a tool that extracts relevant information or by running a tool like scapy or aircrack on the Raspberry Pi to capture and process network data local to the Pi. Only small, digested, processed data is sent back to the server.

Getting Set Up For The Pod

Make sure your node is all set: Deployment/New Node Checklist

Make sure docker installed: Docker/Installing

Pod Containers

Stunnel

Stunnel is a server/client service that allows arbitrary traffic to be transported through an encrypted HTTP over SSL layer (HTTPS). Since port 443 is usually open even on locked-down networks, this is an extremely handy tool for punching through firewalls. Due to the nature of encrypted traffic, the contents of an HTTPS packet cannot be inspected, so services that would otherwise be blocked due to their protocols, like SSH, can pass in and out of the network just fine by being wrapped up in HTTPS.

Here's how the Stunnel Docker container will be set up:

  • Create a Dockerfile (you can download a prepared one, but they are easy enough to make that it is worth doing yourself.)
  • Make a Docker Stunnel container image
  • Run a Docker Stunnel container image
  • Ensure that Stunnel is working and configured properly (ignoring network)
  • Ensure that networking with host is working and configured properly

Get Files

Get the Dockerfile from the git.charlesreid1.com repo: https://git.charlesreid1.com/docker/d-stunnel

$ mkdir ~/docker
$ cd ~/docker
$ git clone https://git.charlesreid1.com/docker/d-stunnel
$ cd d-stunnel

This will also have some supporting scripts and example config files.

Create Certificate

Next step is to create a certificate.

See Stunnel#Certificate

Option 1 is to use Let's Encrypt (recommended). Use the LetsEncrypt page and the generate_letsencrypt_cert.sh script in the d-stunnel repository.

Option 2 is to use a self-signed certificate. See RaspberryPi/SSH Stunnel for details and use the generate_ss_cert.sh script in the d-stunnel repository.

Link to d-stunnel repository: https://git.charlesreid1.com/docker/d-stunnel

Configure Client

Next, configure your client stunnel using stunnel.conf. On a Mac, this will go in /usr/local/etc/stunnel/stunnel.conf. On Ubuntu/Linux, it will go in /etc/stunnel/stunnel.conf. The client machine's configuration should map ports matching whatever you're trying to do. There are some examples in the docker/d-stunnel repository on git.charlesreid1.com: https://git.charlesreid1.com/docker/d-stunnel

These pages have sample client configuration files:

Configure Raspberry Pi Client

Stunnel client config files for Raspberry Pi: https://git.charlesreid1.com/rpi/p-stunnel

Configure Server

Configure the server by setting the server's stunnel.conf file to match the client's and whatever service you're trying to access.

These pages have sample server configuration files:

This is the configuration file that will be copied into the Docker container and used with its stunnel instance. It is recommended you check out https://git.charlesreid1.com/docker/d-stunnel and put it into the d-stunnel/ directory.

TLDR

You have to map ports from container to host, and your host and container have to share the same network interface. Here is what the final run command looks like:

docker run \
	--network=host \
	-p 443:443 -p 22:22 \
	-ti cmr_stunnel \
	/bin/bash

Build Docker stunnel container image from Dockerfile

From the git repo checked out above, which contains a Dockerfile, run docker build to build the image:

$ docker build -t cmr_stunnel .

This may take a minute. Once that's finished make sure Docker now lists the image:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
cmr_stunnel         latest              2b197f506e02        59 seconds ago      219 MB

Networking/Ports Configuration

First, let's talk about how stunnel works, independently of Docker.

Stunnel will expose one port externally (for clients to connect on). Typically, this is 443, but it can be any port. This is the port on which all of the SSL-wrapped traffic will pass. It then forwards that traffic on to another local port (typically this is a port with a service that is not externally exposed, but that isn't a requirement). The configuration file determines which local port the stunnel server will map traffic to.

Now let's talk about how to do this when running stunnel from within Docker.

The Docker container will be running an stunnel service that listens on some port (say 443) and forwards that traffic on to some other port. The hitch is, Docker containers are not, by default, connected to host ports, so we need to explicitly link ports from the container to ports on the host.

The first port we want to map is the port on which stunnel is listening - if stunnel listens on 443 inside the container, we can make that available on the host port 443 by specifying -p 443:443 when we run the docker container.

However, we also need to map the destination port, where stunnel is forwarding traffic to, to the host destination port. If we use a simple example of tunneling SSH traffic through stunnel, we need to link the stunnel Docker container's port 22 to the host's port 22.

Finally, we also need the docker container to share a networking interface with the host - otherwise, the host needs to dedicate a separate listener (on the host) listening to each of the ports that we map. This creates a conflict if there is already an SSH server listening on the port we're trying to bind to. Since these two services are just talking to each other, they should be able to bind to the same network interface. Use the --network=host to force the container and host to share the same network interface.

See Docker/Networking for the setup and configuration files for tunneling SSH over an stunnel SSL connection on port 443.

Here is what the final run command looks like:

docker run \
	--network=host \
	-p 443:443 -p 22:22 \
	-ti cmr_stunnel \
	/bin/bash

Run the Docker stunnel container image

You can fire up the docker container and get a Bash shell:

docker run \
	--network=host \
	-p 443:443 -p 22:22 \
	-ti cmr_stunnel \
	/bin/bash

Running the stunnel command should work okay.

Flags