@@ -121,7 +121,7 @@ table ip {} {{
121
121
} )
122
122
}
123
123
124
- /// Create namespace-side nftables rules for traffic redirection
124
+ /// Create namespace-side nftables rules for traffic redirection and egress filtering
125
125
pub fn new_namespace_table (
126
126
namespace : & str ,
127
127
host_ip : & str ,
@@ -130,26 +130,45 @@ table ip {} {{
130
130
) -> Result < Self > {
131
131
let table_name = "httpjail" . to_string ( ) ;
132
132
133
- // Generate the ruleset for namespace-side DNAT
133
+ // Generate the ruleset for namespace-side DNAT + FILTER
134
134
let ruleset = format ! (
135
135
r#"
136
136
table ip {} {{
137
+ # NAT output chain: redirect HTTP/HTTPS to host proxy
137
138
chain output {{
138
139
type nat hook output priority -100; policy accept;
139
-
140
- # Skip DNS traffic
140
+
141
+ # Skip DNS traffic from NAT processing
141
142
udp dport 53 return
142
143
tcp dport 53 return
143
-
144
- # Redirect HTTP to proxy
144
+
145
+ # Redirect HTTP to proxy running on host
145
146
tcp dport 80 dnat to {}:{}
146
-
147
- # Redirect HTTPS to proxy
147
+
148
+ # Redirect HTTPS to proxy running on host
148
149
tcp dport 443 dnat to {}:{}
149
150
}}
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
+ }}
150
169
}}
151
170
"# ,
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
153
172
) ;
154
173
155
174
debug ! (
0 commit comments