@@ -7,7 +7,7 @@ use crate::network::internal_types::{IsolateOption, PortForwardConfig};
7
7
use ipnet:: IpNet ;
8
8
use iptables:: IPTables ;
9
9
use log:: debug;
10
- use std:: net:: IpAddr ;
10
+ use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr } ;
11
11
12
12
// Chain names
13
13
const NAT : & str = "nat" ;
@@ -66,6 +66,7 @@ impl VarkRule {
66
66
& self . rule
67
67
}
68
68
}
69
+
69
70
// Varkchain is an iptable chain with extra info
70
71
pub struct VarkChain < ' a > {
71
72
// name of chain
@@ -192,17 +193,24 @@ pub fn create_network_chains(chains: Vec<VarkChain<'_>>) -> NetavarkResult<()> {
192
193
Ok ( ( ) )
193
194
}
194
195
195
- pub fn get_network_chains < ' a > (
196
- conn : & ' a IPTables ,
197
- network : IpNet ,
198
- network_hash_name : & ' a str ,
199
- is_ipv6 : bool ,
200
- interface_name : String ,
201
- isolation : IsolateOption ,
202
- dns_port : u16 ,
203
- ) -> Vec < VarkChain < ' a > > {
196
+ pub struct NetworkChainConfig {
197
+ pub network : IpNet ,
198
+ pub network_hash_name : String ,
199
+ pub interface_name : String ,
200
+ pub isolation : IsolateOption ,
201
+ pub dns_port : u16 ,
202
+ pub outbound_addr4 : Option < Ipv4Addr > ,
203
+ pub outbound_addr6 : Option < Ipv6Addr > ,
204
+ }
205
+
206
+ pub fn get_network_chains ( conn : & IPTables , config : NetworkChainConfig ) -> Vec < VarkChain < ' _ > > {
204
207
let mut chains = Vec :: new ( ) ;
205
- let prefixed_network_hash_name = format ! ( "{}-{}" , "NETAVARK" , network_hash_name) ;
208
+ let prefixed_network_hash_name = format ! ( "{}-{}" , "NETAVARK" , config. network_hash_name) ;
209
+
210
+ let is_ipv6 = match config. network {
211
+ IpNet :: V4 ( _) => false ,
212
+ IpNet :: V6 ( _) => true ,
213
+ } ;
206
214
207
215
// NETAVARK-HASH
208
216
let mut hashed_network_chain = VarkChain :: new (
@@ -214,25 +222,51 @@ pub fn get_network_chains<'a>(
214
222
hashed_network_chain. create = true ;
215
223
216
224
hashed_network_chain. build_rule ( VarkRule :: new (
217
- format ! ( "-d {network } -j {ACCEPT}" ) ,
225
+ format ! ( "-d {} -j {}" , config . network , ACCEPT ) ,
218
226
Some ( TeardownPolicy :: OnComplete ) ,
219
227
) ) ;
220
228
221
229
let mut multicast_dest = MULTICAST_NET_V4 ;
222
230
if is_ipv6 {
223
231
multicast_dest = MULTICAST_NET_V6 ;
224
232
}
225
- hashed_network_chain. build_rule ( VarkRule :: new (
226
- format ! ( "! -d {multicast_dest} -j {MASQUERADE}" ) ,
227
- Some ( TeardownPolicy :: OnComplete ) ,
228
- ) ) ;
233
+
234
+ // Use appropriate outbound address based on subnet type
235
+ if is_ipv6 {
236
+ if let Some ( addr6) = config. outbound_addr6 {
237
+ log:: trace!( "Creating IPv6 SNAT rule with outbound address {addr6}" ) ;
238
+ hashed_network_chain. build_rule ( VarkRule :: new (
239
+ format ! ( "! -d {multicast_dest} -j SNAT --to-source {addr6}" ) ,
240
+ Some ( TeardownPolicy :: OnComplete ) ,
241
+ ) ) ;
242
+ } else {
243
+ log:: trace!( "No IPv6 outbound address set, using default MASQUERADE rule" ) ;
244
+ hashed_network_chain. build_rule ( VarkRule :: new (
245
+ format ! ( "! -d {multicast_dest} -j {MASQUERADE}" ) ,
246
+ Some ( TeardownPolicy :: OnComplete ) ,
247
+ ) ) ;
248
+ }
249
+ } else if let Some ( addr4) = config. outbound_addr4 {
250
+ log:: trace!( "Creating IPv4 SNAT rule with outbound address {addr4}" ) ;
251
+ hashed_network_chain. build_rule ( VarkRule :: new (
252
+ format ! ( "! -d {multicast_dest} -j SNAT --to-source {addr4}" ) ,
253
+ Some ( TeardownPolicy :: OnComplete ) ,
254
+ ) ) ;
255
+ } else {
256
+ log:: trace!( "No IPv4 outbound address set, using default MASQUERADE rule" ) ;
257
+ hashed_network_chain. build_rule ( VarkRule :: new (
258
+ format ! ( "! -d {multicast_dest} -j {MASQUERADE}" ) ,
259
+ Some ( TeardownPolicy :: OnComplete ) ,
260
+ ) ) ;
261
+ }
262
+
229
263
chains. push ( hashed_network_chain) ;
230
264
231
265
// POSTROUTING
232
266
let mut postrouting_chain =
233
267
VarkChain :: new ( conn, NAT . to_string ( ) , POSTROUTING . to_string ( ) , None ) ;
234
268
postrouting_chain. build_rule ( VarkRule :: new (
235
- format ! ( "-s {network } -j {prefixed_network_hash_name}" ) ,
269
+ format ! ( "-s {} -j {}" , config . network , prefixed_network_hash_name ) ,
236
270
Some ( TeardownPolicy :: OnComplete ) ,
237
271
) ) ;
238
272
chains. push ( postrouting_chain) ;
@@ -272,7 +306,7 @@ pub fn get_network_chains<'a>(
272
306
) ;
273
307
netavark_isolation_chain_3. create = true ;
274
308
275
- if let IsolateOption :: Normal | IsolateOption :: Strict = isolation {
309
+ if let IsolateOption :: Normal | IsolateOption :: Strict = config . isolation {
276
310
debug ! ( "Add extra isolate rules" ) ;
277
311
// NETAVARK_ISOLATION_1
278
312
let mut netavark_isolation_chain_1 = VarkChain :: new (
@@ -290,7 +324,7 @@ pub fn get_network_chains<'a>(
290
324
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
291
325
} ) ;
292
326
293
- let netavark_isolation_1_target = if let IsolateOption :: Strict = isolation {
327
+ let netavark_isolation_1_target = if let IsolateOption :: Strict = config . isolation {
294
328
// NETAVARK_ISOLATION_1 -i bridge_name ! -o bridge_name -j NETAVARK_ISOLATION_3
295
329
NETAVARK_ISOLATION_3
296
330
} else {
@@ -299,15 +333,16 @@ pub fn get_network_chains<'a>(
299
333
} ;
300
334
netavark_isolation_chain_1. build_rule ( VarkRule {
301
335
rule : format ! (
302
- "-i {interface_name} ! -o {interface_name} -j {netavark_isolation_1_target}"
336
+ "-i {} ! -o {} -j {}" ,
337
+ config. interface_name, config. interface_name, netavark_isolation_1_target
303
338
) ,
304
339
position : Some ( ind) ,
305
340
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
306
341
} ) ;
307
342
308
343
// NETAVARK_ISOLATION_2 -o bridge_name -j DROP
309
344
netavark_isolation_chain_2. build_rule ( VarkRule {
310
- rule : format ! ( "-o {} -j {}" , interface_name, "DROP" ) ,
345
+ rule : format ! ( "-o {} -j {}" , config . interface_name, "DROP" ) ,
311
346
position : Some ( ind) ,
312
347
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
313
348
} ) ;
@@ -328,7 +363,7 @@ pub fn get_network_chains<'a>(
328
363
329
364
// NETAVARK_ISOLATION_3 -o bridge_name -j DROP
330
365
netavark_isolation_chain_3. build_rule ( VarkRule {
331
- rule : format ! ( "-o {} -j {}" , interface_name, "DROP" ) ,
366
+ rule : format ! ( "-o {} -j {}" , config . interface_name, "DROP" ) ,
332
367
position : Some ( ind) ,
333
368
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
334
369
} ) ;
@@ -375,7 +410,10 @@ pub fn get_network_chains<'a>(
375
410
// to gateway when using bridge network with internal dns.
376
411
for proto in [ "udp" , "tcp" ] {
377
412
netavark_input_chain. build_rule ( VarkRule :: new (
378
- format ! ( "-p {proto} -s {network} --dport {dns_port} -j {ACCEPT}" ) ,
413
+ format ! (
414
+ "-p {proto} -s {} --dport {} -j {ACCEPT}" ,
415
+ config. network, config. dns_port
416
+ ) ,
379
417
Some ( TeardownPolicy :: OnComplete ) ,
380
418
) ) ;
381
419
}
@@ -392,14 +430,17 @@ pub fn get_network_chains<'a>(
392
430
// Create incoming traffic rule
393
431
// CNI did this by IP address, this is implemented per subnet
394
432
netavark_forward_chain. build_rule ( VarkRule :: new (
395
- format ! ( "-d {network} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" ) ,
433
+ format ! (
434
+ "-d {} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" ,
435
+ config. network
436
+ ) ,
396
437
Some ( TeardownPolicy :: OnComplete ) ,
397
438
) ) ;
398
439
399
440
// Create outgoing traffic rule
400
441
// CNI did this by IP address, this is implemented per subnet
401
442
netavark_forward_chain. build_rule ( VarkRule :: new (
402
- format ! ( "-s {network } -j ACCEPT" ) ,
443
+ format ! ( "-s {} -j ACCEPT" , config . network ) ,
403
444
Some ( TeardownPolicy :: OnComplete ) ,
404
445
) ) ;
405
446
chains. push ( netavark_forward_chain) ;
0 commit comments