@@ -121,7 +121,7 @@ table ip {} {{
121121 } )
122122 }
123123
124- /// Create namespace-side nftables rules for traffic redirection
124+ /// Create namespace-side nftables rules for traffic redirection and egress filtering
125125 pub fn new_namespace_table (
126126 namespace : & str ,
127127 host_ip : & str ,
@@ -130,26 +130,45 @@ table ip {} {{
130130 ) -> Result < Self > {
131131 let table_name = "httpjail" . to_string ( ) ;
132132
133- // Generate the ruleset for namespace-side DNAT
133+ // Generate the ruleset for namespace-side DNAT + FILTER
134134 let ruleset = format ! (
135135 r#"
136136table ip {} {{
137+ # NAT output chain: redirect HTTP/HTTPS to host proxy
137138 chain output {{
138139 type nat hook output priority -100; policy accept;
139-
140- # Skip DNS traffic
140+
141+ # Skip DNS traffic from NAT processing
141142 udp dport 53 return
142143 tcp dport 53 return
143-
144- # Redirect HTTP to proxy
144+
145+ # Redirect HTTP to proxy running on host
145146 tcp dport 80 dnat to {}:{}
146-
147- # Redirect HTTPS to proxy
147+
148+ # Redirect HTTPS to proxy running on host
148149 tcp dport 443 dnat to {}:{}
149150 }}
151+
152+ # FILTER output chain: block non-HTTP/HTTPS egress
153+ chain outfilter {{
154+ type filter hook output priority 0; policy drop;
155+
156+ # Always allow established/related traffic
157+ ct state established,related accept
158+
159+ # Allow DNS to anywhere
160+ udp dport 53 accept
161+ tcp dport 53 accept
162+
163+ # Explicitly block all other UDP (e.g., QUIC on 443)
164+ ip protocol udp drop
165+
166+ # Allow traffic to the host proxy ports after DNAT
167+ ip daddr {} tcp dport {{ {}, {} }} accept
168+ }}
150169}}
151170"# ,
152- table_name, host_ip, http_port, host_ip, https_port
171+ table_name, host_ip, http_port, host_ip, https_port, host_ip , http_port , https_port
153172 ) ;
154173
155174 debug ! (
0 commit comments