5.7 KiB
5.7 KiB
network-go — Docker Network & Firewall Manager
A Go-based replacement for the firewall/firewall-add shell script. It watches
/etc/user/config/networks.json for changes and reconciles Docker networks,
container connections, and iptables firewall rules using the Docker SDK.
Project Structure
network-go/
├── main.go Entry point: watches config, orchestrates reconciliation
├── config/
│ └── config.go Parses /etc/user/config/networks.json into typed structs
├── docker/
│ └── docker.go Docker SDK wrapper (network create, container connect,
│ container PID for nsenter, route management)
├── firewall/
│ └── firewall.go Orchestrator: translates policies → iptables rules
├── iptables/
│ └── iptables.go Manages iptables CLI: PREROUTING DNAT, POSTROUTING MASQUERADE,
│ FORWARD ACCEPT, nsenter for container network namespaces
├── resolver/
│ └── resolver.go Resolves names → IPs using networks.json config
├── watcher/
│ └── watcher.go Periodic file change detection via MD5 hash polling
├── go.mod / go.sum Module definition with Docker SDK dependency
└── .gitignore
Packages
config
NetworksConfig,NetworkConfig,IPConfig,PolicyConfigstructs matchingnetworks.jsonFirewallRulestruct for resolved executable rules- Helpers:
IsIP,ToCIDR,NetworkPrefix,ParseCIDR,Load
docker
Clientwrappinggithub.com/docker/docker/clientEnsureNetwork— creates a Docker network if it doesn't existConnectContainer/DisconnectContainer— manages container ↔ network membershipGetContainerPID— returns the container PID for nsenterAddRouteInContainer— adds routes inside a container namespace via nsenterWaitForContainerRunning— polls until a container is running
resolver
- Resolves names → IPs using the
networks.jsonconfig only - Looks up by
container_nameandselectorin theipssection - Falls back to prefix matching (e.g.
smarthost-backend-1→ prefixsmarthost)
iptables
- Auto-detects
iptables-legacyvsiptables(matching shell script logic) EnsureIPForward— enables/proc/sys/net/ipv4/ip_forwardEnsureEstablishedRelated— inserts ESTABLISHED,RELATED ACCEPT at top of chainInsertPreroutingRule/InsertPreroutingRuleInContainer— DNAT rulesInsertPostroutingMasquerade— MASQUERADE rulesInsertForwardAccept— FORWARD/DOCKER-USER ACCEPT rules- Rule deletion by line-number + grep pattern matching (matching shell script)
- nsenter-based execution inside container network namespaces
firewall
Orchestratorties all packages togetherReconcileAllruns the full reconciliation cycle:- Enable IP forwarding
- Ensure all Docker networks from config
- Connect containers to networks with assigned IPs
- Apply firewall policies as iptables rules
- Policy → rule mapping:
fromfield → FORWARD ACCEPT rule on DOCKER-USER or FORWARD chainnat: dnatfield → PREROUTING DNAT inside container namespace via nsenter- Interface-based rules (e.g.
wg0) → host-level PREROUTING DNAT
watcher
FileWatcherpolls a file at a configurable interval- Computes MD5 hash on each tick
- Fires
onChangecallback when hash changes Start/Stopfor lifecycle management
Configuration
The file /etc/user/config/networks.json defines:
{
"networks": {
"smarthost-loadbalancer": {
"network_name": "smarthost-loadbalancer",
"subnet": "172.18.103.0/24",
"gateway": "172.18.103.1"
}
},
"ips": {
"172.18.103.2": {
"ip": "172.18.103.2",
"container_name": "smarthostloadbalancer",
"selector": "smarthostloadbalancer",
"service_name": "smarthost-proxy"
}
},
"policies": [
{
"service_name": "smarthost-proxy",
"container_name": "smarthost_loadbalancer",
"selector": "smarthostloadbalancer",
"from": "publicbackend",
"port": 80,
"proto": "tcp"
},
{
"service_name": "smarthost-proxy",
"container_name": "smarthost_loadbalancer",
"selector": "smarthostloadbalancer",
"name": "wireguardproxy",
"iface": "wg0",
"nat": "dnat",
"to": "smarthostloadbalancer",
"port": 80,
"proto": "tcp"
}
]
}
Environment Variables
| Variable | Default | Description |
|---|---|---|
NETWORKS_CONFIG_PATH |
/etc/user/config/networks.json |
Path to the configuration file |
WATCH_PERIOD_SECONDS |
30 |
Polling interval in seconds for config file changes |
DEBUG |
false |
Enable debug output (1 or true) |
Key Differences from Shell Script
Shell Script (firewall-add) |
Go Implementation |
|---|---|
docker ps --format, docker inspect |
Docker SDK (github.com/docker/docker) |
/etc/dns/hosts.local lookup |
networks.json config lookup |
$SOURCE / $TARGET env vars |
from / to fields in networks.json |
| iptables via bash + grep + awk | Go os/exec with structured line matching |
nsenter -t PID -n for container iptables |
nsenter via os/exec in iptables.Manager |
$ROUTE=true + ip route |
docker.Client.AddRouteInContainer() |
| Manual per-rule invocation | Orchestrator.ReconcileAll() batch reconciliation |
Build & Run
go build -o network-go .
./network-go
In Docker:
go build -o network-go .
# Mount Docker socket and config
docker run -v /var/run/docker.sock:/var/run/docker.sock \
-v /etc/user/config:/etc/user/config \
network-go