Skip to content

Commit cd4ae3f

Browse files
[IMP] Modify README
1 parent 1e05222 commit cd4ae3f

1 file changed

Lines changed: 137 additions & 100 deletions

File tree

README.md

Lines changed: 137 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,174 +1,198 @@
1-
# Docker Whitelist Gateway (Multi-Destination Edition)
1+
# Docker Whitelist Gateway
22

3-
A transparent outbound firewall + DNS gateway for Docker internal networks.
3+
Outbound network gateway + filtered DNS for Docker internal networks.
44

5-
This project allows containers attached to **internal (isolated) Docker networks** to
6-
reach selected external destinations while keeping all other outbound traffic blocked.
5+
This project allows containers attached to **internal Docker networks** to reach only a
6+
defined set of external destinations, while preserving internal Docker service
7+
resolution.
78

8-
Unlike classic single-target whitelist proxies, this implementation supports:
9+
It is designed for stacks where:
910

10-
- Multiple external destinations (multi-destination)
11-
- Dynamic DNS resolution
12-
- Automatic subnet detection (no fixed IP configuration)
13-
- Internal service resolution preservation
14-
- Transparent TCP forwarding using iptables + asyncio
11+
- the main application runs on an internal network
12+
- outbound internet access must be restricted
13+
- only specific domains or IPs should be reachable
14+
- internal Docker service names must continue to resolve normally
1515

1616
---
1717

18-
## Architecture Overview
18+
## Architecture
1919

20-
The gateway is designed for environments where:
20+
The setup usually uses two containers:
2121

22-
- The main service runs in a Docker **internal network**
23-
- Outbound internet access must be restricted
24-
- Only specific domains/IPs should be reachable
25-
- Internal service discovery must keep working
22+
1. **gateway container**
2623

27-
The architecture typically uses two containers:
24+
- enables IPv4 forwarding
25+
- applies `iptables` and `ipset` rules
26+
- performs NAT/masquerading for outbound traffic
27+
- periodically resolves allowed hosts and populates the whitelist
2828

29-
1. **gateway container**
30-
- Runs iptables rules
31-
- Runs async TCP forwarder
32-
- Runs controlled DNS (dnsmasq)
33-
- Whitelists allowed destinations
34-
2. **net_setup sidecar (optional but recommended)**
35-
- Shares network namespace with the main service
36-
- Rewrites default route to gateway
37-
- Rewrites /etc/resolv.conf to use gateway DNS
29+
2. **net_setup sidecar**
30+
- shares the network namespace of the main app container
31+
- rewrites the default route so traffic exits through the gateway
32+
- optionally starts a **local dnsmasq**
33+
- generates internal DNS entries automatically from Docker metadata
3834

3935
---
4036

41-
## How It Works
37+
## How it works
4238

43-
### Traffic Redirection
39+
### Outbound traffic filtering
4440

45-
The gateway:
41+
The gateway container maintains an `ipset` containing the IPs resolved from
42+
`ALLOWED_HOSTS`.
4643

47-
- Installs NAT REDIRECT rules
48-
- Captures outbound TCP traffic
49-
- Recovers original destination using `SO_ORIGINAL_DST`
50-
- Forwards only if destination is allowed
44+
Traffic is allowed only when the destination IP matches that set.
5145

52-
All other outbound traffic is dropped.
46+
The gateway also installs:
47+
48+
- a `FORWARD` rule allowing `RELATED,ESTABLISHED`
49+
- a `FORWARD` rule allowing destinations present in the whitelist ipset
50+
- a `POSTROUTING MASQUERADE` rule for outbound NAT
51+
52+
This means the application can only reach external destinations whose IPs are currently
53+
present in the whitelist.
5354

5455
---
5556

56-
### Controlled DNS
57+
### DNS behavior
5758

58-
When the main container switches its resolver to the gateway:
59+
There are two DNS layers:
5960

60-
- Internal Docker names must still resolve
61-
- External domains must be filtered
61+
#### 1. Local app DNS (inside the app namespace)
6262

63-
The gateway:
63+
When `DNS_LOCAL=1` is enabled in `net_setup`:
6464

65-
- Uses Docker DNS to resolve internal services
66-
- Runs dnsmasq for controlled external resolution
67-
- Returns `0.0.0.0` for non-allowed domains
65+
- `dnsmasq` listens on `127.0.0.1`
66+
- `/etc/resolv.conf` is rewritten to use `127.0.0.1`
67+
- external resolution is restricted to domains derived from `ALLOWED_HOSTS`
68+
- internal Docker service names are served from an autogenerated hosts file
6869

69-
Allowed example:
70+
#### 2. Internal Docker service resolution
7071

71-
transfer.einsamobile.de → 194.26.180.120
72+
Internal names are not maintained manually.
7273

73-
Blocked example:
74+
Instead, the sidecar can generate `/run/dnsmasq-internal.hosts` from Docker metadata
75+
using the Docker socket. This includes:
7476

75-
www.google.com → 0.0.0.0
77+
- Compose service names (`db`, `smtp`, `odoo`, etc.)
78+
- explicit network aliases (`wdb_internal`, etc.)
79+
- container names when useful
80+
81+
This preserves internal service discovery without relying on Docker DNS as an upstream
82+
resolver.
7683

7784
---
7885

79-
## Required Capability
86+
## Required capability
8087

8188
```yaml
8289
cap_add:
8390
- NET_ADMIN
8491
```
8592
86-
---
87-
88-
## Environment Variables
89-
90-
### ALLOWED_HOSTS (Required)
91-
92-
Space-separated list of domains or IPs allowed for outbound access.
93+
For automatic internal DNS generation, the net setup sidecar also needs access to the
94+
Docker socket:
9395
9496
```yaml
95-
environment:
96-
ALLOWED_HOSTS: "api.example.com smtp.example.com 1.2.3.4"
97+
volumes:
98+
- /var/run/docker.sock:/var/run/docker.sock:ro
9799
```
98100
99101
---
100102
101-
### PORT
103+
## Environment variables
102104
103-
Default: `*`
105+
### Common
104106
105-
Defines allowed TCP ports.
107+
#### `ALLOWED_HOSTS` (required)
106108

107-
Examples:
109+
Space-separated list of allowed external domains and/or IPs.
110+
111+
Example:
108112

109113
```yaml
110-
PORT: "443"
111-
PORT: "80 443 8080"
112-
PORT: "21 50000-51000"
114+
ALLOWED_HOSTS: "graph.microsoft.com api.example.com 1.2.3.4"
113115
```
114116

117+
Domains are used for:
118+
119+
- whitelist IP resolution in the gateway
120+
- filtered external DNS in local dnsmasq
121+
122+
IP literals are added directly to the whitelist.
123+
115124
---
116125

117-
### PRE_RESOLVE
126+
#### `DNS_UPSTREAMS`
118127

119-
Default: `0`
128+
Default:
120129

121-
When enabled (`1`):
130+
```yaml
131+
DNS_UPSTREAMS: "1.1.1.1 8.8.8.8"
132+
```
122133

123-
- The gateway resolves allowed domains itself
124-
- Refreshes periodically
125-
- Avoids dependency on system DNS
134+
Upstream resolvers used by dnsmasq for allowed external domains.
126135

127136
---
128137

129-
### RESOLVE_INTERVAL
138+
### Gateway mode
130139

131-
Default: `60`
140+
#### `MODE_RUN=gateway`
132141

133-
DNS refresh interval in seconds when `PRE_RESOLVE=1`.
142+
Runs the container as the outbound network gateway.
134143

135-
---
144+
Optional:
136145

137-
### DNS_UPSTREAMS
138-
139-
Default: `1.1.1.1 8.8.8.8`
146+
```yaml
147+
IPSET_NAME: "whitelist"
148+
REFRESH_INTERVAL: "300"
149+
```
140150

141-
Upstream DNS servers used by dnsmasq.
151+
- `IPSET_NAME`: name of the whitelist ipset
152+
- `REFRESH_INTERVAL`: refresh interval in seconds for resolving allowed hosts
142153

143154
---
144155

145-
### DNS_INTERNAL_NAMES
156+
### Net setup mode
146157

147-
Optional.
158+
#### `MODE_RUN=net_setup`
148159

149-
Defines internal Docker service names that must always resolve.
160+
Runs the container as the sidecar that configures routing and DNS for the main app.
150161

151-
Example:
162+
Required:
163+
164+
```yaml
165+
GATEWAY_NAME: "proxy_general"
166+
```
167+
168+
This must resolve to the gateway container on the shared Docker network.
169+
170+
Optional:
152171

153172
```yaml
154-
DNS_INTERNAL_NAMES: "db smtp redis backend gateway"
173+
DNS_LOCAL: "1"
174+
DNS_INTERNAL_FROM_DOCKER: "1"
175+
DOCKER_PROJECT: "my-project"
176+
DOCKER_PRIMARY_SERVICE: "odoo"
177+
DNS_DOCKER_REFRESH_INTERVAL: "5"
155178
```
156179

157-
Only required if the gateway replaces Docker's default resolver and you want
158-
deterministic internal resolution.
180+
- `DNS_LOCAL=1`: enable local dnsmasq in the app namespace
181+
- `DNS_INTERNAL_FROM_DOCKER=1`: generate internal DNS entries from Docker metadata
182+
- `DOCKER_PROJECT`: Compose project name used to discover related containers
183+
- `DOCKER_PRIMARY_SERVICE`: main service whose visible networks define the DNS scope
184+
- `DNS_DOCKER_REFRESH_INTERVAL`: refresh interval for autogenerated internal hosts
159185

160186
---
161187

162-
## Multi-Destination Example (Generic Service)
188+
## Example
163189

164190
```yaml
165191
services:
166192
app:
167193
image: my-app
168194
networks:
169195
- internal
170-
cap_add:
171-
- NET_ADMIN
172196
depends_on:
173197
- gateway
174198
@@ -177,9 +201,16 @@ services:
177201
network_mode: "service:app"
178202
cap_add:
179203
- NET_ADMIN
204+
volumes:
205+
- /var/run/docker.sock:/var/run/docker.sock:ro
180206
environment:
181-
MODE_RUN: net_setup
182-
GATEWAY_NAME: gateway
207+
MODE_RUN: "net_setup"
208+
GATEWAY_NAME: "gateway"
209+
DNS_LOCAL: "1"
210+
DNS_INTERNAL_FROM_DOCKER: "1"
211+
DOCKER_PROJECT: "my-project"
212+
DOCKER_PRIMARY_SERVICE: "app"
213+
ALLOWED_HOSTS: "graph.microsoft.com api.example.com"
183214
184215
gateway:
185216
image: docker-whitelist-gateway:latest
@@ -189,8 +220,8 @@ services:
189220
- internal
190221
- public
191222
environment:
192-
ALLOWED_HOSTS: "api.stripe.com smtp.mailgun.org ftp.partner.com"
193-
PRE_RESOLVE: 1
223+
MODE_RUN: "gateway"
224+
ALLOWED_HOSTS: "graph.microsoft.com api.example.com"
194225
195226
networks:
196227
internal:
@@ -200,15 +231,21 @@ networks:
200231

201232
---
202233

203-
## Summary
234+
## Current behavior summary
204235

205-
Docker Whitelist Gateway provides:
236+
This implementation now provides:
237+
238+
- outbound filtering based on destination IP whitelist
239+
- automatic refresh of allowed destination IPs
240+
- local filtered DNS for the application
241+
- automatic internal Docker name resolution from Docker metadata
242+
- no need to maintain `DNS_INTERNAL_NAMES` manually in normal setups
243+
244+
---
206245

207-
- Transparent outbound filtering
208-
- DNS-level control
209-
- Multi-destination support
210-
- Automatic dynamic routing
211-
- Clean separation between service and firewall logic
246+
## Notes
212247

213-
It is designed for secure containerized environments where outbound access must be
214-
explicitly controlled.
248+
- The gateway healthcheck validates the current `iptables`/`ipset`-based setup.
249+
- Internal DNS generation depends on the Docker socket and Compose metadata.
250+
- External DNS resolution is intentionally restricted to domains derived from
251+
`ALLOWED_HOSTS`.

0 commit comments

Comments
 (0)