@@ -7,13 +7,14 @@ import (
7
7
"log/slog"
8
8
"os"
9
9
"os/exec"
10
+ "syscall"
10
11
"time"
11
12
)
12
13
13
14
// LinuxJail implements Jailer using Linux network namespaces
14
15
type LinuxJail struct {
15
- logger * slog.Logger
16
- namespace string
16
+ logger * slog.Logger
17
+ // namespace string
17
18
vethHost string // Host-side veth interface name for iptables rules
18
19
commandEnv []string
19
20
httpProxyPort int
@@ -27,8 +28,8 @@ type LinuxJail struct {
27
28
28
29
func NewLinuxJail (config Config ) (* LinuxJail , error ) {
29
30
return & LinuxJail {
30
- logger : config .Logger ,
31
- namespace : newNamespaceName (),
31
+ logger : config .Logger ,
32
+ // namespace: newNamespaceName(),
32
33
httpProxyPort : config .HttpProxyPort ,
33
34
configDir : config .ConfigDir ,
34
35
caCertPath : config .CACertPath ,
@@ -46,21 +47,25 @@ func (l *LinuxJail) Start() error {
46
47
e := getEnvs (l .configDir , l .caCertPath )
47
48
l .commandEnv = mergeEnvs (e , map [string ]string {})
48
49
50
+ return nil
51
+ }
52
+
53
+ func (l * LinuxJail ) ConfigureChildProcess (pid int ) error {
49
54
// Setup DNS configuration BEFORE creating namespace
50
55
// This ensures the namespace-specific resolv.conf is available when namespace is created
51
- err := l .setupDNS ()
52
- if err != nil {
53
- return fmt .Errorf ("failed to setup DNS: %v" , err )
54
- }
56
+ // err := l.setupDNS()
57
+ // if err != nil {
58
+ // return fmt.Errorf("failed to setup DNS: %v", err)
59
+ // }
55
60
56
61
// Create namespace
57
- err = l .createNamespace ()
58
- if err != nil {
59
- return fmt .Errorf ("failed to create namespace: %v" , err )
60
- }
62
+ // err = l.createNamespace()
63
+ // if err != nil {
64
+ // return fmt.Errorf("failed to create namespace: %v", err)
65
+ // }
61
66
62
67
// Setup networking within namespace
63
- err = l .setupNetworking ()
68
+ err : = l .setupNetworking (pid )
64
69
if err != nil {
65
70
return fmt .Errorf ("failed to setup networking: %v" , err )
66
71
}
@@ -76,12 +81,25 @@ func (l *LinuxJail) Start() error {
76
81
77
82
// Command returns an exec.Cmd configured to run within the network namespace
78
83
func (l * LinuxJail ) Command (command []string ) * exec.Cmd {
79
- l .logger .Debug ("Creating command with namespace" , "namespace" , l .namespace )
80
-
81
- cmdArgs := []string {"netns" , "exec" , l .namespace }
82
- cmdArgs = append (cmdArgs , command ... )
83
-
84
- cmd := exec .Command ("ip" , cmdArgs ... )
84
+ l .logger .Debug ("Creating command with namespace" )
85
+ //l.logger.Debug("Creating command with namespace", "namespace", l.namespace)
86
+
87
+ //cmdArgs := []string{"netns", "exec", l.namespace}
88
+ //cmdArgs = append(cmdArgs, command...)
89
+ //
90
+ //cmd := exec.Command("ip", cmdArgs...)
91
+ //cmd.Env = l.commandEnv
92
+
93
+ cmd := exec .Command (command [0 ], command [1 :]... )
94
+ cmd .SysProcAttr = & syscall.SysProcAttr {
95
+ Cloneflags : syscall .CLONE_NEWUSER | syscall .CLONE_NEWNET ,
96
+ UidMappings : []syscall.SysProcIDMap {
97
+ {ContainerID : 0 , HostID : os .Getuid (), Size : 1 },
98
+ },
99
+ GidMappings : []syscall.SysProcIDMap {
100
+ {ContainerID : 0 , HostID : os .Getgid (), Size : 1 },
101
+ },
102
+ }
85
103
cmd .Env = l .commandEnv
86
104
87
105
return cmd
@@ -106,34 +124,36 @@ func (l *LinuxJail) Close() error {
106
124
}
107
125
108
126
// Clean up namespace-specific DNS config directory
109
- netnsEtc := fmt .Sprintf ("/etc/netns/%s" , l .namespace )
110
- err = os .RemoveAll (netnsEtc )
111
- if err != nil {
112
- l .logger .Warn ("Failed to remove namespace DNS config" , "dir" , netnsEtc , "error" , err )
113
- // Continue with other cleanup
114
- }
127
+ // netnsEtc := fmt.Sprintf("/etc/netns/%s", l.namespace)
128
+ // err = os.RemoveAll(netnsEtc)
129
+ // if err != nil {
130
+ // l.logger.Warn("Failed to remove namespace DNS config", "dir", netnsEtc, "error", err)
131
+ // // Continue with other cleanup
132
+ // }
115
133
116
134
// Remove network namespace
117
- err = l .removeNamespace ()
118
- if err != nil {
119
- return fmt .Errorf ("failed to remove namespace: %v" , err )
120
- }
135
+ // err = l.removeNamespace()
136
+ // if err != nil {
137
+ // return fmt.Errorf("failed to remove namespace: %v", err)
138
+ // }
121
139
122
140
return nil
123
141
}
124
142
125
143
// createNamespace creates a new network namespace
126
- func (l * LinuxJail ) createNamespace () error {
127
- cmd := exec .Command ("ip" , "netns" , "add" , l .namespace )
128
- err := cmd .Run ()
129
- if err != nil {
130
- return fmt .Errorf ("failed to create namespace: %v" , err )
131
- }
132
- return nil
133
- }
144
+ // func (l *LinuxJail) createNamespace() error {
145
+ // cmd := exec.Command("ip", "netns", "add", l.namespace)
146
+ // err := cmd.Run()
147
+ // if err != nil {
148
+ // return fmt.Errorf("failed to create namespace: %v", err)
149
+ // }
150
+ // return nil
151
+ // }
134
152
135
153
// setupNetworking configures networking within the namespace
136
- func (l * LinuxJail ) setupNetworking () error {
154
+ func (l * LinuxJail ) setupNetworking (pidInt int ) error {
155
+ PID := fmt .Sprintf ("%v" , pidInt )
156
+
137
157
// Create veth pair with short names (Linux interface names limited to 15 chars)
138
158
// Generate unique ID to avoid conflicts
139
159
uniqueID := fmt .Sprintf ("%d" , time .Now ().UnixNano ()% 10000000 ) // 7 digits max
@@ -148,18 +168,18 @@ func (l *LinuxJail) setupNetworking() error {
148
168
command * exec.Cmd
149
169
}{
150
170
{"create veth pair" , exec .Command ("ip" , "link" , "add" , vethHost , "type" , "veth" , "peer" , "name" , vethNetJail )},
151
- {"move veth to namespace" , exec .Command ("ip" , "link" , "set" , vethNetJail , "netns" , l . namespace )},
171
+ {"move veth to namespace" , exec .Command ("ip" , "link" , "set" , vethNetJail , "netns" , PID )},
152
172
{"configure host veth" , exec .Command ("ip" , "addr" , "add" , "192.168.100.1/24" , "dev" , vethHost )},
153
173
{"bring up host veth" , exec .Command ("ip" , "link" , "set" , vethHost , "up" )},
154
- {"configure namespace veth" , exec .Command ("ip " , "netns " , "exec " , l . namespace , "ip" , "addr" , "add" , "192.168.100.2/24" , "dev" , vethNetJail )},
155
- {"bring up namespace veth" , exec .Command ("ip " , "netns " , "exec " , l . namespace , "ip" , "link" , "set" , vethNetJail , "up" )},
156
- {"bring up loopback" , exec .Command ("ip " , "netns " , "exec " , l . namespace , "ip" , "link" , "set" , "lo" , "up" )},
157
- {"set default route in namespace" , exec .Command ("ip " , "netns " , "exec " , l . namespace , "ip" , "route" , "add" , "default" , "via" , "192.168.100.1" )},
174
+ {"configure namespace veth" , exec .Command ("nsenter " , "-t " , PID , "-n " , "--" , "ip" , "addr" , "add" , "192.168.100.2/24" , "dev" , vethNetJail )},
175
+ {"bring up namespace veth" , exec .Command ("nsenter " , "-t " , PID , "-n " , "--" , "ip" , "link" , "set" , vethNetJail , "up" )},
176
+ {"bring up loopback" , exec .Command ("nsenter " , "-t " , PID , "-n " , "--" , "ip" , "link" , "set" , "lo" , "up" )},
177
+ {"set default route in namespace" , exec .Command ("nsenter " , "-t " , PID , "-n " , "--" , "ip" , "route" , "add" , "default" , "via" , "192.168.100.1" )},
158
178
}
159
179
160
180
for _ , command := range setupCmds {
161
- if err := command .command .Run (); err != nil {
162
- return fmt .Errorf ("failed to %s: %v" , command .description , err )
181
+ if output , err := command .command .CombinedOutput (); err != nil {
182
+ return fmt .Errorf ("failed to %s: %v, output: %s, args: %v " , command .description , err , output , command . command . Args )
163
183
}
164
184
}
165
185
@@ -169,32 +189,32 @@ func (l *LinuxJail) setupNetworking() error {
169
189
// setupDNS configures DNS resolution for the namespace
170
190
// This ensures reliable DNS resolution by using public DNS servers
171
191
// instead of relying on the host's potentially complex DNS configuration
172
- func (l * LinuxJail ) setupDNS () error {
173
- // Always create namespace-specific resolv.conf with reliable public DNS servers
174
- // This avoids issues with systemd-resolved, Docker DNS, and other complex setups
175
- netnsEtc := fmt .Sprintf ("/etc/netns/%s" , l .namespace )
176
- err := os .MkdirAll (netnsEtc , 0755 )
177
- if err != nil {
178
- return fmt .Errorf ("failed to create /etc/netns directory: %v" , err )
179
- }
180
-
181
- // Write custom resolv.conf with multiple reliable public DNS servers
182
- resolvConfPath := fmt .Sprintf ("%s/resolv.conf" , netnsEtc )
183
- dnsConfig := `# Custom DNS for network namespace
184
- nameserver 8.8.8.8
185
- nameserver 8.8.4.4
186
- nameserver 1.1.1.1
187
- nameserver 9.9.9.9
188
- options timeout:2 attempts:2
189
- `
190
- err = os .WriteFile (resolvConfPath , []byte (dnsConfig ), 0644 )
191
- if err != nil {
192
- return fmt .Errorf ("failed to write namespace-specific resolv.conf: %v" , err )
193
- }
194
-
195
- l .logger .Debug ("DNS setup completed" )
196
- return nil
197
- }
192
+ // func (l *LinuxJail) setupDNS() error {
193
+ // // Always create namespace-specific resolv.conf with reliable public DNS servers
194
+ // // This avoids issues with systemd-resolved, Docker DNS, and other complex setups
195
+ // netnsEtc := fmt.Sprintf("/etc/netns/%s", l.namespace)
196
+ // err := os.MkdirAll(netnsEtc, 0755)
197
+ // if err != nil {
198
+ // return fmt.Errorf("failed to create /etc/netns directory: %v", err)
199
+ // }
200
+ //
201
+ // // Write custom resolv.conf with multiple reliable public DNS servers
202
+ // resolvConfPath := fmt.Sprintf("%s/resolv.conf", netnsEtc)
203
+ // dnsConfig := `# Custom DNS for network namespace
204
+ // nameserver 8.8.8.8
205
+ // nameserver 8.8.4.4
206
+ // nameserver 1.1.1.1
207
+ // nameserver 9.9.9.9
208
+ // options timeout:2 attempts:2
209
+ // `
210
+ // err = os.WriteFile(resolvConfPath, []byte(dnsConfig), 0644)
211
+ // if err != nil {
212
+ // return fmt.Errorf("failed to write namespace-specific resolv.conf: %v", err)
213
+ // }
214
+ //
215
+ // l.logger.Debug("DNS setup completed")
216
+ // return nil
217
+ // }
198
218
199
219
// setupIptables configures iptables rules for comprehensive TCP traffic interception
200
220
func (l * LinuxJail ) setupIptables () error {
@@ -279,11 +299,11 @@ func (l *LinuxJail) cleanupNetworking() error {
279
299
}
280
300
281
301
// removeNamespace removes the network namespace
282
- func (l * LinuxJail ) removeNamespace () error {
283
- cmd := exec .Command ("ip" , "netns" , "del" , l .namespace )
284
- err := cmd .Run ()
285
- if err != nil {
286
- return fmt .Errorf ("failed to remove namespace: %v" , err )
287
- }
288
- return nil
289
- }
302
+ // func (l *LinuxJail) removeNamespace() error {
303
+ // cmd := exec.Command("ip", "netns", "del", l.namespace)
304
+ // err := cmd.Run()
305
+ // if err != nil {
306
+ // return fmt.Errorf("failed to remove namespace: %v", err)
307
+ // }
308
+ // return nil
309
+ // }
0 commit comments