A transparent TCP whitelist proxy based on iptables and asyncio.
Docker supports internal networks; but when you use them, you cannot open outbound connections unless the container is attached to a public network.
This proxy allows selected external endpoints to be reachable from containers attached to restricted internal networks.
Typical use cases:
- Allowing connections only to specific external APIs.
- Allowing limited outbound access while keeping containers isolated.
- Whitelisting external services such as SMTP, payment gateways, font/CDN APIs, etc.
The proxy works by:
- Installing iptables NAT REDIRECT rules (requires
CAP_NET_ADMIN) - Running a single TCP listener
- Redirecting inbound traffic to that listener
- Recovering the original destination port using
SO_ORIGINAL_DST - Forwarding traffic to
TARGET:<original_port>
Unlike previous versions, this implementation:
- Does not spawn one process per port
- Uses a single async TCP server
- Scales better under load
- Handles DNS refresh more reliably
This implementation requires:
cap_add:
- NET_ADMINWithout this capability, the container cannot configure iptables and will fail at startup.
Required. Hostname where incoming connections will be forwarded.
Default: * (all TCP ports allowed)
Defines which TCP ports are redirected and proxied.
Examples:
Allow all ports (default):
environment:
TARGET: api.example.comRestrict to HTTPS only:
environment:
TARGET: api.example.com
PORT: "443"Multiple ports:
environment:
TARGET: api.example.com
PORT: "80 443 8080"Port ranges:
environment:
TARGET: ftp.example.com
PORT: "21 50000-51000"If PORT is not set, all TCP ports are allowed.
Default: 0
Set to 1 to resolve TARGET using the configured NAMESERVERS instead of the system
resolver.
When enabled, DNS is refreshed periodically.
Default: 60
Interval in seconds to refresh DNS resolution when PRE_RESOLVE=1.
If the IP changes, new connections automatically use the new address.
Default: 208.67.222.222 8.8.8.8 208.67.220.220 8.8.4.4
Used only when PRE_RESOLVE=1.
Default: 15000
Internal port where the proxy listens after iptables redirection.
Default: 0
Set to 1 to enable HTTP-based healthcheck using pycurl.
Default: http://$TARGET/
Default: 2000
Default: 0
Set to 1 to enable SMTP healthcheck using pycurl.
Default: smtp://$TARGET/
Default: HELP
Default: 2000
Default: 0
Set to 1 to log all connections.
services:
fonts_googleapis_proxy:
image: ghcr.io/tecnativa/docker-whitelist:latest
cap_add:
- NET_ADMIN
networks:
default:
aliases:
- fonts.googleapis.com
public:
environment:
TARGET: fonts.googleapis.com
PRE_RESOLVE: 1