@@ -18,6 +18,7 @@ import (
18
18
type Linux struct {
19
19
config Config
20
20
namespace string
21
+ vethHost string // Host-side veth interface name for iptables rules
21
22
logger * slog.Logger
22
23
preparedEnv map [string ]string
23
24
procAttr * syscall.SysProcAttr
@@ -26,9 +27,10 @@ type Linux struct {
26
27
// newLinux creates a new Linux network jail instance
27
28
func newLinux (config Config , logger * slog.Logger ) (* Linux , error ) {
28
29
return & Linux {
29
- config : config ,
30
- namespace : newNamespaceName (),
31
- logger : logger ,
30
+ config : config ,
31
+ namespace : newNamespaceName (),
32
+ logger : logger ,
33
+ preparedEnv : make (map [string ]string ),
32
34
}, nil
33
35
}
34
36
@@ -63,12 +65,14 @@ func (l *Linux) Open() error {
63
65
64
66
// Prepare environment once during setup
65
67
l .logger .Debug ("Preparing environment" )
66
- l .preparedEnv = make (map [string ]string )
67
68
68
69
// Start with current environment
69
70
for _ , envVar := range os .Environ () {
70
71
if parts := strings .SplitN (envVar , "=" , 2 ); len (parts ) == 2 {
71
- l .preparedEnv [parts [0 ]] = parts [1 ]
72
+ // Only set if not already set by SetEnv
73
+ if _ , exists := l .preparedEnv [parts [0 ]]; ! exists {
74
+ l .preparedEnv [parts [0 ]] = parts [1 ]
75
+ }
72
76
}
73
77
}
74
78
@@ -193,6 +197,9 @@ func (l *Linux) setupNetworking() error {
193
197
vethHost := fmt .Sprintf ("veth_h_%s" , uniqueID ) // veth_h_1234567 = 14 chars
194
198
vethNetJail := fmt .Sprintf ("veth_n_%s" , uniqueID ) // veth_n_1234567 = 14 chars
195
199
200
+ // Store veth interface name for iptables rules
201
+ l .vethHost = vethHost
202
+
196
203
setupCmds := []struct {
197
204
description string
198
205
command * exec.Cmd
@@ -246,42 +253,40 @@ options timeout:2 attempts:2
246
253
return nil
247
254
}
248
255
249
- // setupIptables configures iptables rules for traffic redirection
256
+ // setupIptables configures iptables rules for comprehensive TCP traffic interception
250
257
func (l * Linux ) setupIptables () error {
251
258
// Enable IP forwarding
252
259
cmd := exec .Command ("sysctl" , "-w" , "net.ipv4.ip_forward=1" )
253
260
cmd .Run () // Ignore error
254
261
255
- // NAT rules for outgoing traffic
262
+ // NAT rules for outgoing traffic (MASQUERADE for return traffic)
256
263
cmd = exec .Command ("iptables" , "-t" , "nat" , "-A" , "POSTROUTING" , "-s" , "192.168.100.0/24" , "-j" , "MASQUERADE" )
257
264
err := cmd .Run ()
258
265
if err != nil {
259
266
return fmt .Errorf ("failed to add NAT rule: %v" , err )
260
267
}
261
268
262
- // Redirect HTTP traffic to proxy
263
- cmd = exec .Command ("ip" , "netns" , "exec" , l .namespace , "iptables" , "-t" , "nat" , "-A" , "OUTPUT" ,
264
- "-p" , "tcp" , "--dport" , "80" , "-j" , "DNAT" , "--to-destination" , fmt .Sprintf ("192.168.100.1:%d" , l .config .HTTPPort ))
265
- err = cmd .Run ()
266
- if err != nil {
267
- return fmt .Errorf ("failed to add HTTP redirect rule: %v" , err )
268
- }
269
-
270
- // Redirect HTTPS traffic to proxy
271
- cmd = exec .Command ("ip" , "netns" , "exec" , l .namespace , "iptables" , "-t" , "nat" , "-A" , "OUTPUT" ,
272
- "-p" , "tcp" , "--dport" , "443" , "-j" , "DNAT" , "--to-destination" , fmt .Sprintf ("192.168.100.1:%d" , l .config .HTTPSPort ))
269
+ // COMPREHENSIVE APPROACH: Intercept ALL TCP traffic from namespace
270
+ // Use PREROUTING on host to catch traffic after it exits namespace but before routing
271
+ // This ensures NO TCP traffic can bypass the proxy
272
+ cmd = exec .Command ("iptables" , "-t" , "nat" , "-A" , "PREROUTING" , "-i" , l .vethHost , "-p" , "tcp" , "-j" , "REDIRECT" , "--to-ports" , fmt .Sprintf ("%d" , l .config .HTTPSPort ))
273
273
err = cmd .Run ()
274
274
if err != nil {
275
- return fmt .Errorf ("failed to add HTTPS redirect rule: %v" , err )
275
+ return fmt .Errorf ("failed to add comprehensive TCP redirect rule: %v" , err )
276
276
}
277
277
278
+ l .logger .Debug ("Comprehensive TCP jailing enabled" , "interface" , l .vethHost , "proxy_port" , l .config .HTTPSPort )
278
279
return nil
279
280
}
280
281
281
282
// removeIptables removes iptables rules
282
283
func (l * Linux ) removeIptables () error {
284
+ // Remove comprehensive TCP redirect rule
285
+ cmd := exec .Command ("iptables" , "-t" , "nat" , "-D" , "PREROUTING" , "-i" , l .vethHost , "-p" , "tcp" , "-j" , "REDIRECT" , "--to-ports" , fmt .Sprintf ("%d" , l .config .HTTPSPort ))
286
+ cmd .Run () // Ignore errors during cleanup
287
+
283
288
// Remove NAT rule
284
- cmd : = exec .Command ("iptables" , "-t" , "nat" , "-D" , "POSTROUTING" , "-s" , "192.168.100.0/24" , "-j" , "MASQUERADE" )
289
+ cmd = exec .Command ("iptables" , "-t" , "nat" , "-D" , "POSTROUTING" , "-s" , "192.168.100.0/24" , "-j" , "MASQUERADE" )
285
290
cmd .Run () // Ignore errors during cleanup
286
291
287
292
return nil
@@ -295,4 +300,4 @@ func (l *Linux) removeNamespace() error {
295
300
return fmt .Errorf ("failed to remove namespace: %v" , err )
296
301
}
297
302
return nil
298
- }
303
+ }
0 commit comments