23 Jul

Tutorial: IP Whitelisting for Docker Containers

You can use iptables to restrict network access to an individual container without altering the Host’s rules or introducing external firewalls.

Why?

Some potential use cases:

  1. I have an app that’s not ready for production but needs to be tested on a production server.
  2. I have multi-tenancy in my SaaS and the customers want to restrict usage of a container just to their IP range.
  3. I host services (databases, proxies, cache…) that rely on IP-based whitelist authorization

How?

Install IP tables in a docker container and use the docker exec command to alter the rules.

Here’s an example of IP based restriction for an Nginx container

Requirements

  1. A VPS ( DigitalOcean or Vultr work— Free $10 Credit) with Docker
  2. 2 different public IP addresses to test from. You can toggle a VPN or SSH into another machine you have.

Getting Started

I have a staging container on a shared VPS that should be accessed only from a range of IPs (say an office VPN )

We will call the machines and IPs as follows

A ) 222.100.100.100 — The VPS

B) 222.200.200.200 — Trusted Source IP

Step 1. Prepare your VPS

Install Docker and confirm that you can access your firewall is open. Some providers like EC2 require that you manually override Security Groups to allow external incoming traffic.

Launch a basic Nginx container that listens on all IP addresses (0.0.0.0) on port 8080

Using iptables within a container requires additional network capabilities forreasons stated here. So, we also add NET_ADMIN and NET_RAW capabilities.

docker pull nginx
docker run --cap-add=NET_ADMIN --cap-add=NET_RAW --name app1 -d -p 0.0.0.0:8080:80 nginx

Test that it works

curl http://222.100.100.100:8080

should print the Nginx welcome screen on all machines.

Step 2. Install IP Tables

Many Docker images come with iptables pre-installed. Just in case, install it via exec:

docker exec app1 apt update
docker exec app1 apt install iptables -y

Verify it works:

docker exec app1 iptables -S

It should output:

-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

Step 3. Block All Traffic

First, we block all traffic to the port that is bound in the container. Here, it is port 80, not 8080.

docker exec app1 iptables -A INPUT -p tcp --dport 80 -j DROP

Verify that it’s blocked

From an external machine, curl http://222.100.100.100:8080 should not work.

Step 4. Whitelist IPs

Then, we white list the trusted source IPs:

docker exec app1 iptables -I INPUT -p tcp --dport 80 --source 222.200.200.200 -j ACCEPT

Notice the -I flag which prepends to the rule file ensuring the white lists have higher precedence over the rule we added in Step 3.

curl http://222.100.100.100:8080

This will work only from the white listed IP. If you can access it from another source, it means something was misconfigured.

Step 5. Remove Whitelist IPs

To remove a whitelist, you can retrieve a list of all your rules:

docker exec app1 iptables -S

and then copy/paste the rule to the -D command, which drops it

docker exec app1 iptables -D INPUT -p tcp — dport 80 — source 222.200.200.200 -j ACCEPT

Step 6. Testing

You can use https://www.geoscreenshot.com to test HTTP access from many IPs.

05 Jul

Research: The Web Proxy Authentication Problem

One of the security concerns of deploying private proxies is ensuring that anonymous crawlers and port scanner do not gain access to it. Many proxy providers mandate that their users manually white-list their IPs to get access to the proxy but few users have stable static IPs. Other providers support username/password authentication but many clients such as Google Chrome do not natively support this scheme.

I researched a few open-source solutions for bridging this gap, here were my findings:

Problems

  1. I am trying to use paid proxy X but it requires either IP-based or HTTP Proxy-Auth based authentication, I want a proxy with no auth requirements that works well with browsers.

Projects Explored

Glider

This was my first choices. It’s lightweight, supports round robin rotation between upstream proxies and supports many protocols.

Doesn’t support Auth proxies yet https://github.com/nadoo/glider/issues/15

Go Proxy

I have this running in production and it works well. Very easy to install and seems to support many protocols. Unfortunately, the documentation isn’t clear on upstream proxies.

Filed an issue here https://github.com/snail007/goproxy/issues/112

MITM Proxy

This is the only proxy I got to work with an HTTP upstream. Unfortunately, it injects it’s own certs and doesn’t support non-intercepting proxying for upstreams.

Squid

Squid is heavy, taking ~180MB of memory on my local machine so it probably will not scale for me. Officially, it supports proxy chaining and others have reported success with it. My attempts haven’t worked, it ignores the cache peer rules and connects directly.

Privoxy

Also claims to support authenticated proxies officially. I haven’t gotten it past DNS resolution for an non-authenticated upstream proxy.

3Proxy

Claims to support proxy chaining with username/password authentication out of the box. The documentation isn’t clear on credential config. Issues here https://github.com/z3APA3A/3proxy/issues/165https://github.com/z3APA3A/3proxy/issues/102 https://github.com/z3APA3A/3proxy/issues/20