@@ -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,52 @@ 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 {
250
+ if let Some ( addr4) = config. outbound_addr4 {
251
+ log:: trace!( "Creating IPv4 SNAT rule with outbound address {}" , addr4) ;
252
+ hashed_network_chain. build_rule ( VarkRule :: new (
253
+ format ! ( "! -d {multicast_dest} -j SNAT --to-source {}" , addr4) ,
254
+ Some ( TeardownPolicy :: OnComplete ) ,
255
+ ) ) ;
256
+ } else {
257
+ log:: trace!( "No IPv4 outbound address set, using default MASQUERADE rule" ) ;
258
+ hashed_network_chain. build_rule ( VarkRule :: new (
259
+ format ! ( "! -d {multicast_dest} -j {MASQUERADE}" ) ,
260
+ Some ( TeardownPolicy :: OnComplete ) ,
261
+ ) ) ;
262
+ }
263
+ }
229
264
chains. push ( hashed_network_chain) ;
230
265
231
266
// POSTROUTING
232
267
let mut postrouting_chain =
233
268
VarkChain :: new ( conn, NAT . to_string ( ) , POSTROUTING . to_string ( ) , None ) ;
234
269
postrouting_chain. build_rule ( VarkRule :: new (
235
- format ! ( "-s {network } -j {prefixed_network_hash_name}" ) ,
270
+ format ! ( "-s {} -j {}" , config . network , prefixed_network_hash_name ) ,
236
271
Some ( TeardownPolicy :: OnComplete ) ,
237
272
) ) ;
238
273
chains. push ( postrouting_chain) ;
@@ -272,7 +307,7 @@ pub fn get_network_chains<'a>(
272
307
) ;
273
308
netavark_isolation_chain_3. create = true ;
274
309
275
- if let IsolateOption :: Normal | IsolateOption :: Strict = isolation {
310
+ if let IsolateOption :: Normal | IsolateOption :: Strict = config . isolation {
276
311
debug ! ( "Add extra isolate rules" ) ;
277
312
// NETAVARK_ISOLATION_1
278
313
let mut netavark_isolation_chain_1 = VarkChain :: new (
@@ -290,7 +325,7 @@ pub fn get_network_chains<'a>(
290
325
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
291
326
} ) ;
292
327
293
- let netavark_isolation_1_target = if let IsolateOption :: Strict = isolation {
328
+ let netavark_isolation_1_target = if let IsolateOption :: Strict = config . isolation {
294
329
// NETAVARK_ISOLATION_1 -i bridge_name ! -o bridge_name -j NETAVARK_ISOLATION_3
295
330
NETAVARK_ISOLATION_3
296
331
} else {
@@ -299,15 +334,16 @@ pub fn get_network_chains<'a>(
299
334
} ;
300
335
netavark_isolation_chain_1. build_rule ( VarkRule {
301
336
rule : format ! (
302
- "-i {interface_name} ! -o {interface_name} -j {netavark_isolation_1_target}"
337
+ "-i {} ! -o {} -j {}" ,
338
+ config. interface_name, config. interface_name, netavark_isolation_1_target
303
339
) ,
304
340
position : Some ( ind) ,
305
341
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
306
342
} ) ;
307
343
308
344
// NETAVARK_ISOLATION_2 -o bridge_name -j DROP
309
345
netavark_isolation_chain_2. build_rule ( VarkRule {
310
- rule : format ! ( "-o {} -j {}" , interface_name, "DROP" ) ,
346
+ rule : format ! ( "-o {} -j {}" , config . interface_name, "DROP" ) ,
311
347
position : Some ( ind) ,
312
348
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
313
349
} ) ;
@@ -328,7 +364,7 @@ pub fn get_network_chains<'a>(
328
364
329
365
// NETAVARK_ISOLATION_3 -o bridge_name -j DROP
330
366
netavark_isolation_chain_3. build_rule ( VarkRule {
331
- rule : format ! ( "-o {} -j {}" , interface_name, "DROP" ) ,
367
+ rule : format ! ( "-o {} -j {}" , config . interface_name, "DROP" ) ,
332
368
position : Some ( ind) ,
333
369
td_policy : Some ( TeardownPolicy :: OnComplete ) ,
334
370
} ) ;
@@ -375,7 +411,10 @@ pub fn get_network_chains<'a>(
375
411
// to gateway when using bridge network with internal dns.
376
412
for proto in [ "udp" , "tcp" ] {
377
413
netavark_input_chain. build_rule ( VarkRule :: new (
378
- format ! ( "-p {proto} -s {network} --dport {dns_port} -j {ACCEPT}" ) ,
414
+ format ! (
415
+ "-p {proto} -s {} --dport {} -j {ACCEPT}" ,
416
+ config. network, config. dns_port
417
+ ) ,
379
418
Some ( TeardownPolicy :: OnComplete ) ,
380
419
) ) ;
381
420
}
@@ -392,14 +431,17 @@ pub fn get_network_chains<'a>(
392
431
// Create incoming traffic rule
393
432
// CNI did this by IP address, this is implemented per subnet
394
433
netavark_forward_chain. build_rule ( VarkRule :: new (
395
- format ! ( "-d {network} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" ) ,
434
+ format ! (
435
+ "-d {} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" ,
436
+ config. network
437
+ ) ,
396
438
Some ( TeardownPolicy :: OnComplete ) ,
397
439
) ) ;
398
440
399
441
// Create outgoing traffic rule
400
442
// CNI did this by IP address, this is implemented per subnet
401
443
netavark_forward_chain. build_rule ( VarkRule :: new (
402
- format ! ( "-s {network } -j ACCEPT" ) ,
444
+ format ! ( "-s {} -j ACCEPT" , config . network ) ,
403
445
Some ( TeardownPolicy :: OnComplete ) ,
404
446
) ) ;
405
447
chains. push ( netavark_forward_chain) ;
0 commit comments