DNS override
Make the public registry hostnames resolve to the firewall, so existing install commands are protected with no per-tool config.
With a DNS override, registry.npmjs.org, pypi.org, and files.pythonhosted.org resolve to the firewall instead of the real registries. Package managers keep their default settings. Roll it out with corporate DNS or an MDM-pushed hosts file, and prove it first on one machine with /etc/hosts.
How it differs from the base setup
The base setup uses path routing: clients call https://sfw.example.com/npm/.... A DNS override needs domain-based routing: the firewall answers for the real registry hostnames directly.
| Path routing | Domain routing (this page) | |
|---|---|---|
| Client config | Required | None |
| Certificate covers | sfw.example.com | Each registry hostname |
| PyPI downloads | Rewritten through the firewall | files.pythonhosted.org must also be overridden |
1. Certificate with the registry hostnames
cd ~/socket-fw
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ssl/privkey.pem \
-out ssl/fullchain.pem \
-subj "/CN=sfw.example.com" \
-addext "subjectAltName=DNS:sfw.example.com,DNS:registry.npmjs.org,DNS:pypi.org,DNS:files.pythonhosted.org"
chmod 644 ssl/fullchain.pem ssl/privkey.pem2. socket.yml with domain-based routing
socket.yml with domain-based routingThis replaces the path-routing socket.yml from Block installs with Firewall, which the other pages use. Back it up first so you can restore it:
cp socket.yml socket.yml.path-routingRunning path routing and domain routing in one instance isn't covered here. Confirm with Socket before combining them.
socket:
api_url: https://api.socket.dev
fail_open: true
ports:
http: 8080
https: 8443
registries:
npm:
domains: [registry.npmjs.org]
upstream: https://registry.npmjs.org
pypi:
domains: [pypi.org, files.pythonhosted.org]
upstream: https://pypi.org
upstreamis requiredWithout
upstream, the firewall skips the registry (WARN: Skipping npm: missing domains or upstream) and returns 404 for everything, while/healthstill reports OK.
Keep the compose file from Block installs with Firewall. The firewall must be on 443, because clients connect to the registry hostnames on the standard port.
docker compose up -d --force-recreate
sleep 15
docker compose logs socket-firewall | grep "Generating .* configuration for"You should see one line per registry (npm, pypi). If a registry is missing, check for the Skipping warning.
Don't override DNS on the firewall hostThe firewall reaches the real registries by name. If the firewall host also resolves
registry.npmjs.orgto itself, requests loop. Leave the firewall host (and its container's DNS) on normal resolution.
3. Prove it on one machine
On a test laptop, replace 10.0.0.5 with the firewall's IP:
sudo sh -c 'cat >> /etc/hosts <<HOSTS
10.0.0.5 registry.npmjs.org
10.0.0.5 pypi.org
10.0.0.5 files.pythonhosted.org
HOSTS'Trust the firewall certificate (see Configure registry: dev), then:
npm config get registry # still https://registry.npmjs.org/
npm cache clean --force
npm install lodash # succeeds, through the firewall
npm install lodahs # 403, blockedTo undo, remove the three lines from /etc/hosts. To return the firewall to path routing, cp socket.yml.path-routing socket.yml && docker compose up -d --force-recreate.
IPv6 bypass
/etc/hostsentries only override the IPv4 lookup. On a client with IPv6, DNS can still return the real registry's IPv6 (AAAA) addresses, and installs can go straight to the registry without touching the firewall. Check withgetent ahosts(below): only the firewall's address may appear. For the single-machine demo, disable IPv6 on the test machine or add IPv6 entries pointing at the firewall. For rollout, suppress AAAA records for these hostnames in corporate DNS.
4. Roll out
Pick one:
- Corporate DNS: A records (or a resolver policy) for the three hostnames pointing at the firewall, scoped to the client networks you want covered. Suppress or override the AAAA records too.
- MDM: push the same
/etc/hostslines plus the firewall CA as a trusted root. On macOS with Jamf, use a configuration profile for the certificate and a policy script for the hosts entries.
Track coverage by matching the client_ip in firewall decision events against your MDM, DHCP, or VPN records. See Data.
Verify
-
docker compose logs socket-firewall | grep "Generating .* configuration for"shows npm and pypi -
getent ahosts registry.npmjs.org(Linux) ordscacheutil -q host -a name registry.npmjs.org(macOS) returns only the firewall's address, with no real IPv6 addresses -
npm install lodahsreturns 403 with no registry config on the client -
pip install requestssucceeds (provesfiles.pythonhosted.orgis covered) - The firewall logs show the client's IP
Troubleshooting
| Symptom | Fix |
|---|---|
| Certificate error | The cert's SAN list is missing a hostname, or the client doesn't trust the CA |
| pip resolves but wheels fail | files.pythonhosted.org is missing from DNS, the SAN, or domains |
| Everything hangs or loops | The firewall host is resolving the registries to itself |
| Every request returns the "Error 404 - Socket Firewall" page | A registry is missing upstream, so no routes loaded |
| Some installs skip the firewall | The client is using IPv6. See the IPv6 bypass callout |
Reference
Updated 8 days ago