@@ -13,8 +13,9 @@ iptables -t nat -X
1313iptables -t mangle -F
1414iptables -t mangle -X
1515ipset destroy github-anthropic 2> /dev/null || true
16+ ipset destroy google-all-ips 2> /dev/null || true
17+ ipset destroy google-customer-ips 2> /dev/null || true
1618
17- # 2. Selectively restore ONLY internal Docker DNS resolution
1819if [ -n " $DOCKER_DNS_RULES " ]; then
1920 echo " Restoring Docker DNS rules..."
2021 iptables -t nat -N DOCKER_OUTPUT 2> /dev/null || true
2425 echo " No Docker DNS rules to restore"
2526fi
2627
27- # First allow DNS and localhost before any restrictions
28- # Allow outbound DNS
2928iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
30- # Allow inbound DNS responses
3129iptables -A INPUT -p udp --sport 53 -j ACCEPT
32- # Allow outbound SSH
3330iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
34- # Allow inbound SSH responses
3531iptables -A INPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
36- # Allow localhost
3732iptables -A INPUT -i lo -j ACCEPT
3833iptables -A OUTPUT -o lo -j ACCEPT
3934
40- # Create ipset with CIDR support
4135ipset create github-anthropic hash:net
4236ipset create google-all-ips hash:net
4337ipset create google-customer-ips hash:net
@@ -53,46 +47,6 @@ if ! echo "$gh_ranges" | jq -e '.web and .api and .git' >/dev/null; then
5347 echo " ERROR: GitHub API response missing required fields"
5448 exit 1
5549fi
56-
57- GOOGLE_ALL_IP_URL=" https://www.gstatic.com/ipranges/goog.json"
58- GOOGLE_CLOUD_CUSTOMER_IP_URL=" https://www.gstatic.com/ipranges/cloud.json"
59-
60- echo " Fetching Google All IPs (goog.json)..."
61- goog_ips=$( curl -s $GOOGLE_ALL_IP_URL )
62- if [ -z " $goog_ips " ]; then
63- echo " ERROR: Failed to fetch Google All IPs"
64- exit 1
65- fi
66-
67- echo " Fetching Google Cloud Customer IPs (cloud.json)..."
68- cloud_ips=$( curl -s $GOOGLE_CLOUD_CUSTOMER_IP_URL )
69- if [ -z " $cloud_ips " ]; then
70- echo " ERROR: Failed to fetch Google Cloud Customer IPs"
71- exit 1
72- fi
73-
74- echo " Populating goog-all-ips ipset..."
75- GOOG_NETBLOCKS=$( echo " $goog_ips " | jq -r ' .prefixes[] | select(.ipv4Prefix) | .ipv4Prefix' | aggregate -q)
76- if [ -z " $GOOG_NETBLOCKS " ]; then
77- echo " ERROR: No IPv4 prefixes found in goog.json"
78- exit 1
79- fi
80-
81- while read -r cidr; do
82- echo " Adding Google range $cidr "
83- ipset add google-all-ips " $cidr " 2> /dev/null || true
84- done < <( echo " $GOOG_NETBLOCKS " )
85-
86- CLOUD_NETBLOCKS=$( echo " $cloud_ips " | jq -r ' .prefixes[] | select(.ipv4Prefix) | .ipv4Prefix' | aggregate -q)
87- if [ -z " $CLOUD_NETBLOCKS " ]; then
88- echo " ERROR: No IPv4 prefixes found in cloud.json"
89- exit 1
90- fi
91- while read -r cidr; do
92- echo " Blocking Google range $cidr "
93- ipset add google-customer-ips " $cidr " 2> /dev/null || true
94- done < <( echo " $CLOUD_NETBLOCKS " )
95-
9650echo " Processing GitHub IPs..."
9751while read -r cidr; do
9852 if [[ ! " $cidr " =~ ^[0-9]{1,3}\. [0-9]{1,3}\. [0-9]{1,3}\. [0-9]{1,3}/[0-9]{1,2}$ ]]; then
@@ -103,7 +57,6 @@ while read -r cidr; do
10357 ipset add github-anthropic " $cidr "
10458done < <( echo " $gh_ranges " | jq -r ' (.web + .api + .git)[]' | aggregate -q)
10559
106- # Resolve and add other allowed domains
10760for domain in \
10861 " api.anthropic.com" \
10962 " generativelanguage.googleapis.com" \
@@ -125,34 +78,67 @@ for domain in \
12578 done < <( echo " $ips " )
12679done
12780
128- # Get host IP from default route
81+ GOOGLE_CLOUD_CUSTOMER_IP_URL=" https://www.gstatic.com/ipranges/cloud.json"
82+ echo " Fetching gcloud customer IPs $GOOGLE_CLOUD_CUSTOMER_IP_URL ."
83+ cloud_ips=$( curl -s $GOOGLE_CLOUD_CUSTOMER_IP_URL )
84+ if [ -z " $cloud_ips " ]; then
85+ echo " ERROR: Failed to fetch Google Cloud Customer IPs"
86+ exit 1
87+ fi
88+ CLOUD_NETBLOCKS=$( echo " $cloud_ips " | jq -r ' .prefixes[] | select(.ipv4Prefix) | .ipv4Prefix' | aggregate -q)
89+ if [ -z " $CLOUD_NETBLOCKS " ]; then
90+ echo " ERROR: No IPv4 prefixes found in cloud.json"
91+ exit 1
92+ fi
93+ while read -r cidr; do
94+ echo " Blocking Google range $cidr "
95+ ipset add google-customer-ips " $cidr " 2> /dev/null || true
96+ done < <( echo " $CLOUD_NETBLOCKS " )
97+
98+ # Get all IPs in Google Cloud
99+ GOOGLE_ALL_IP_URL=" https://www.gstatic.com/ipranges/goog.json"
100+ echo " Fetching gcloud full ip ranges $GOOGLE_ALL_IP_URL ."
101+ goog_ips=$( curl -s $GOOGLE_ALL_IP_URL )
102+ if [ -z " $goog_ips " ]; then
103+ echo " ERROR: Failed to fetch Google All IPs"
104+ exit 1
105+ fi
106+ echo " Populating goog-all-ips ipset..."
107+ GOOG_NETBLOCKS=$( echo " $goog_ips " | jq -r ' .prefixes[] | select(.ipv4Prefix) | .ipv4Prefix' | aggregate -q)
108+ if [ -z " $GOOG_NETBLOCKS " ]; then
109+ echo " ERROR: No IPv4 prefixes found in goog.json"
110+ exit 1
111+ fi
112+ while read -r cidr; do
113+ echo " Adding Google range $cidr "
114+ ipset add google-all-ips " $cidr " 2> /dev/null || true
115+ done < <( echo " $GOOG_NETBLOCKS " )
116+
117+
129118HOST_IP=$( ip route | grep default | cut -d" " -f3)
130119if [ -z " $HOST_IP " ]; then
131120 echo " ERROR: Failed to detect host IP"
132121 exit 1
133122fi
134-
135123HOST_NETWORK=$( echo " $HOST_IP " | sed " s/\.[0-9]*$/.0\/24/" )
136124echo " Host network detected as: $HOST_NETWORK "
137125
138- # Set up remaining iptables rules
139126iptables -A INPUT -s " $HOST_NETWORK " -j ACCEPT
140127iptables -A OUTPUT -d " $HOST_NETWORK " -j ACCEPT
141-
142- # Set default policies to DROP first
143128iptables -P INPUT DROP
144129iptables -P FORWARD DROP
145130iptables -P OUTPUT DROP
146-
147- # First allow established connections for already approved traffic
148131iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
149132iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
150133
151134# Allow GitHub and Anthropic
152135iptables -A OUTPUT -m set --match-set github-anthropic dst -j ACCEPT
153- # Block all Google Cloud customer IPs (do not include github/anthropic)
136+ # Block all Google Cloud customer IPs
137+ # since this rule is after github-anthropic ACCEPT it shouldn't block any IPs in both sets
154138iptables -A OUTPUT -m set --match-set google-customer-ips dst -j REJECT --reject-with icmp-admin-prohibited
155139# Allow complement of All Google IPs and Customer Google Cloud IPs
140+ # since this rule is after google-customer-ips REJECT it should allow
141+ # IPs used by google not assigned to customers
156142iptables -A OUTPUT -m set --match-set google-all-ips dst -j ACCEPT
157143
158144# Explicitly REJECT all other outbound traffic for immediate feedback
@@ -166,8 +152,6 @@ if curl --connect-timeout 5 https://example.com >/dev/null 2>&1; then
166152else
167153 echo " Firewall verification passed - unable to reach https://example.com as expected"
168154fi
169-
170- # Verify GitHub API access
171155if ! curl --connect-timeout 5 https://api.github.com/zen > /dev/null 2>&1 ; then
172156 echo " ERROR: Firewall verification failed - unable to reach https://api.github.com"
173157 exit 1
0 commit comments