1 #[cfg(test)] 2 mod nat_test; 3 4 use crate::error::*; 5 use crate::vnet::chunk::Chunk; 6 use crate::vnet::net::UDP_STR; 7 8 use std::collections::{HashMap, HashSet}; 9 use std::net::IpAddr; 10 use std::ops::Add; 11 use std::sync::atomic::{AtomicU16, Ordering}; 12 use std::sync::Arc; 13 use std::time::SystemTime; 14 use tokio::sync::Mutex; 15 use tokio::time::Duration; 16 17 const DEFAULT_NAT_MAPPING_LIFE_TIME: Duration = Duration::from_secs(30); 18 19 // EndpointDependencyType defines a type of behavioral dependendency on the 20 // remote endpoint's IP address or port number. This is used for the two 21 // kinds of behaviors: 22 // - Port Mapping behavior 23 // - Filtering behavior 24 // See: https://tools.ietf.org/html/rfc4787 25 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 26 pub enum EndpointDependencyType { 27 // EndpointIndependent means the behavior is independent of the endpoint's address or port 28 EndpointIndependent, 29 // EndpointAddrDependent means the behavior is dependent on the endpoint's address 30 EndpointAddrDependent, 31 // EndpointAddrPortDependent means the behavior is dependent on the endpoint's address and port 32 EndpointAddrPortDependent, 33 } 34 35 impl Default for EndpointDependencyType { 36 fn default() -> Self { 37 EndpointDependencyType::EndpointIndependent 38 } 39 } 40 41 // NATMode defines basic behavior of the NAT 42 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 43 pub enum NatMode { 44 // NATModeNormal means the NAT behaves as a standard NAPT (RFC 2663). 45 Normal, 46 // NATModeNAT1To1 exhibits 1:1 DNAT where the external IP address is statically mapped to 47 // a specific local IP address with port number is preserved always between them. 48 // When this mode is selected, mapping_behavior, filtering_behavior, port_preservation and 49 // mapping_life_time of NATType are ignored. 50 Nat1To1, 51 } 52 53 impl Default for NatMode { 54 fn default() -> Self { 55 NatMode::Normal 56 } 57 } 58 59 // NATType has a set of parameters that define the behavior of NAT. 60 #[derive(Default, Debug, Copy, Clone)] 61 pub struct NatType { 62 pub mode: NatMode, 63 pub mapping_behavior: EndpointDependencyType, 64 pub filtering_behavior: EndpointDependencyType, 65 pub hair_pining: bool, // Not implemented yet 66 pub port_preservation: bool, // Not implemented yet 67 pub mapping_life_time: Duration, 68 } 69 70 #[derive(Default, Debug, Clone)] 71 pub(crate) struct NatConfig { 72 pub(crate) name: String, 73 pub(crate) nat_type: NatType, 74 pub(crate) mapped_ips: Vec<IpAddr>, // mapped IPv4 75 pub(crate) local_ips: Vec<IpAddr>, // local IPv4, required only when the mode is NATModeNAT1To1 76 } 77 78 #[derive(Debug, Clone)] 79 pub(crate) struct Mapping { 80 proto: String, // "udp" or "tcp" 81 local: String, // "<local-ip>:<local-port>" 82 mapped: String, // "<mapped-ip>:<mapped-port>" 83 bound: String, // key: "[<remote-ip>[:<remote-port>]]" 84 filters: Arc<Mutex<HashSet<String>>>, // key: "[<remote-ip>[:<remote-port>]]" 85 expires: Arc<Mutex<SystemTime>>, // time to expire 86 } 87 88 impl Default for Mapping { 89 fn default() -> Self { 90 Mapping { 91 proto: String::new(), // "udp" or "tcp" 92 local: String::new(), // "<local-ip>:<local-port>" 93 mapped: String::new(), // "<mapped-ip>:<mapped-port>" 94 bound: String::new(), // key: "[<remote-ip>[:<remote-port>]]" 95 filters: Arc::new(Mutex::new(HashSet::new())), // key: "[<remote-ip>[:<remote-port>]]" 96 expires: Arc::new(Mutex::new(SystemTime::now())), // time to expire 97 } 98 } 99 } 100 101 #[derive(Default, Debug, Clone)] 102 pub(crate) struct NetworkAddressTranslator { 103 pub(crate) name: String, 104 pub(crate) nat_type: NatType, 105 pub(crate) mapped_ips: Vec<IpAddr>, // mapped IPv4 106 pub(crate) local_ips: Vec<IpAddr>, // local IPv4, required only when the mode is NATModeNAT1To1 107 pub(crate) outbound_map: Arc<Mutex<HashMap<String, Arc<Mapping>>>>, // key: "<proto>:<local-ip>:<local-port>[:remote-ip[:remote-port]] 108 pub(crate) inbound_map: Arc<Mutex<HashMap<String, Arc<Mapping>>>>, // key: "<proto>:<mapped-ip>:<mapped-port>" 109 pub(crate) udp_port_counter: Arc<AtomicU16>, 110 } 111 112 impl NetworkAddressTranslator { 113 pub(crate) fn new(config: NatConfig) -> Result<Self> { 114 let mut nat_type = config.nat_type; 115 116 if nat_type.mode == NatMode::Nat1To1 { 117 // 1:1 NAT behavior 118 nat_type.mapping_behavior = EndpointDependencyType::EndpointIndependent; 119 nat_type.filtering_behavior = EndpointDependencyType::EndpointIndependent; 120 nat_type.port_preservation = true; 121 nat_type.mapping_life_time = Duration::from_secs(0); 122 123 if config.mapped_ips.is_empty() { 124 return Err(Error::ErrNatRequriesMapping); 125 } 126 if config.mapped_ips.len() != config.local_ips.len() { 127 return Err(Error::ErrMismatchLengthIp); 128 } 129 } else { 130 // Normal (NAPT) behavior 131 nat_type.mode = NatMode::Normal; 132 if nat_type.mapping_life_time == Duration::from_secs(0) { 133 nat_type.mapping_life_time = DEFAULT_NAT_MAPPING_LIFE_TIME; 134 } 135 } 136 137 Ok(NetworkAddressTranslator { 138 name: config.name, 139 nat_type, 140 mapped_ips: config.mapped_ips, 141 local_ips: config.local_ips, 142 outbound_map: Arc::new(Mutex::new(HashMap::new())), 143 inbound_map: Arc::new(Mutex::new(HashMap::new())), 144 udp_port_counter: Arc::new(AtomicU16::new(0)), 145 }) 146 } 147 148 pub(crate) fn get_paired_mapped_ip(&self, loc_ip: &IpAddr) -> Option<&IpAddr> { 149 for (i, ip) in self.local_ips.iter().enumerate() { 150 if ip == loc_ip { 151 return self.mapped_ips.get(i); 152 } 153 } 154 None 155 } 156 157 pub(crate) fn get_paired_local_ip(&self, mapped_ip: &IpAddr) -> Option<&IpAddr> { 158 for (i, ip) in self.mapped_ips.iter().enumerate() { 159 if ip == mapped_ip { 160 return self.local_ips.get(i); 161 } 162 } 163 None 164 } 165 166 pub(crate) async fn translate_outbound( 167 &self, 168 from: &(dyn Chunk + Send + Sync), 169 ) -> Result<Option<Box<dyn Chunk + Send + Sync>>> { 170 let mut to = from.clone_to(); 171 172 if from.network() == UDP_STR { 173 if self.nat_type.mode == NatMode::Nat1To1 { 174 // 1:1 NAT behavior 175 let src_addr = from.source_addr(); 176 if let Some(src_ip) = self.get_paired_mapped_ip(&src_addr.ip()) { 177 to.set_source_addr(&format!("{}:{}", src_ip, src_addr.port()))?; 178 } else { 179 log::debug!( 180 "[{}] drop outbound chunk {} with not route", 181 self.name, 182 from 183 ); 184 return Ok(None); // silently discard 185 } 186 } else { 187 // Normal (NAPT) behavior 188 let bound = match self.nat_type.mapping_behavior { 189 EndpointDependencyType::EndpointIndependent => "".to_owned(), 190 EndpointDependencyType::EndpointAddrDependent => { 191 from.get_destination_ip().to_string() 192 } 193 EndpointDependencyType::EndpointAddrPortDependent => { 194 from.destination_addr().to_string() 195 } 196 }; 197 198 let filter_key = match self.nat_type.filtering_behavior { 199 EndpointDependencyType::EndpointIndependent => "".to_owned(), 200 EndpointDependencyType::EndpointAddrDependent => { 201 from.get_destination_ip().to_string() 202 } 203 EndpointDependencyType::EndpointAddrPortDependent => { 204 from.destination_addr().to_string() 205 } 206 }; 207 208 let o_key = format!("udp:{}:{}", from.source_addr(), bound); 209 let name = self.name.clone(); 210 211 let m_mapped = if let Some(m) = self.find_outbound_mapping(&o_key).await { 212 let mut filters = m.filters.lock().await; 213 if !filters.contains(&filter_key) { 214 log::debug!( 215 "[{}] permit access from {} to {}", 216 name, 217 filter_key, 218 m.mapped 219 ); 220 filters.insert(filter_key); 221 } 222 m.mapped.clone() 223 } else { 224 // Create a new Mapping 225 let udp_port_counter = self.udp_port_counter.load(Ordering::SeqCst); 226 let mapped_port = 0xC000 + udp_port_counter; 227 if udp_port_counter == 0xFFFF - 0xC000 { 228 self.udp_port_counter.store(0, Ordering::SeqCst); 229 } else { 230 self.udp_port_counter.fetch_add(1, Ordering::SeqCst); 231 } 232 233 let m = if let Some(mapped_ips_first) = self.mapped_ips.first() { 234 Mapping { 235 proto: "udp".to_owned(), 236 local: from.source_addr().to_string(), 237 bound, 238 mapped: format!("{}:{}", mapped_ips_first, mapped_port), 239 filters: Arc::new(Mutex::new(HashSet::new())), 240 expires: Arc::new(Mutex::new( 241 SystemTime::now().add(self.nat_type.mapping_life_time), 242 )), 243 } 244 } else { 245 return Err(Error::ErrNatRequriesMapping); 246 }; 247 248 { 249 let mut outbound_map = self.outbound_map.lock().await; 250 outbound_map.insert(o_key.clone(), Arc::new(m.clone())); 251 } 252 253 let i_key = format!("udp:{}", m.mapped); 254 255 log::debug!( 256 "[{}] created a new NAT binding oKey={} i_key={}", 257 self.name, 258 o_key, 259 i_key 260 ); 261 log::debug!( 262 "[{}] permit access from {} to {}", 263 self.name, 264 filter_key, 265 m.mapped 266 ); 267 268 { 269 let mut filters = m.filters.lock().await; 270 filters.insert(filter_key); 271 } 272 273 let m_mapped = m.mapped.clone(); 274 { 275 let mut inbound_map = self.inbound_map.lock().await; 276 inbound_map.insert(i_key, Arc::new(m)); 277 } 278 m_mapped 279 }; 280 281 to.set_source_addr(&m_mapped)?; 282 } 283 284 log::debug!( 285 "[{}] translate outbound chunk from {} to {}", 286 self.name, 287 from, 288 to 289 ); 290 291 return Ok(Some(to)); 292 } 293 294 Err(Error::ErrNonUdpTranslationNotSupported) 295 } 296 297 pub(crate) async fn translate_inbound( 298 &self, 299 from: &(dyn Chunk + Send + Sync), 300 ) -> Result<Option<Box<dyn Chunk + Send + Sync>>> { 301 let mut to = from.clone_to(); 302 303 if from.network() == UDP_STR { 304 if self.nat_type.mode == NatMode::Nat1To1 { 305 // 1:1 NAT behavior 306 let dst_addr = from.destination_addr(); 307 if let Some(dst_ip) = self.get_paired_local_ip(&dst_addr.ip()) { 308 let dst_port = from.destination_addr().port(); 309 to.set_destination_addr(&format!("{}:{}", dst_ip, dst_port))?; 310 } else { 311 return Err(Error::Other(format!( 312 "drop {} as {:?}", 313 from, 314 Error::ErrNoAssociatedLocalAddress 315 ))); 316 } 317 } else { 318 // Normal (NAPT) behavior 319 let filter_key = match self.nat_type.filtering_behavior { 320 EndpointDependencyType::EndpointIndependent => "".to_owned(), 321 EndpointDependencyType::EndpointAddrDependent => { 322 from.get_source_ip().to_string() 323 } 324 EndpointDependencyType::EndpointAddrPortDependent => { 325 from.source_addr().to_string() 326 } 327 }; 328 329 let i_key = format!("udp:{}", from.destination_addr()); 330 if let Some(m) = self.find_inbound_mapping(&i_key).await { 331 { 332 let filters = m.filters.lock().await; 333 if !filters.contains(&filter_key) { 334 return Err(Error::Other(format!( 335 "drop {} as the remote {} {:?}", 336 from, 337 filter_key, 338 Error::ErrHasNoPermission 339 ))); 340 } 341 } 342 343 // See RFC 4847 Section 4.3. Mapping Refresh 344 // a) Inbound refresh may be useful for applications with no outgoing 345 // UDP traffic. However, allowing inbound refresh may allow an 346 // external attacker or misbehaving application to keep a Mapping 347 // alive indefinitely. This may be a security risk. Also, if the 348 // process is repeated with different ports, over time, it could 349 // use up all the ports on the NAT. 350 351 to.set_destination_addr(&m.local)?; 352 } else { 353 return Err(Error::Other(format!( 354 "drop {} as {:?}", 355 from, 356 Error::ErrNoNatBindingFound 357 ))); 358 } 359 } 360 361 log::debug!( 362 "[{}] translate inbound chunk from {} to {}", 363 self.name, 364 from, 365 to 366 ); 367 368 return Ok(Some(to)); 369 } 370 371 Err(Error::ErrNonUdpTranslationNotSupported) 372 } 373 374 // caller must hold the mutex 375 pub(crate) async fn find_outbound_mapping(&self, o_key: &str) -> Option<Arc<Mapping>> { 376 let mapping_life_time = self.nat_type.mapping_life_time; 377 let mut expired = false; 378 let (in_key, out_key) = { 379 let outbound_map = self.outbound_map.lock().await; 380 if let Some(m) = outbound_map.get(o_key) { 381 let now = SystemTime::now(); 382 383 { 384 let mut expires = m.expires.lock().await; 385 // check if this Mapping is expired 386 if now.duration_since(*expires).is_ok() { 387 expired = true; 388 } else { 389 *expires = now.add(mapping_life_time); 390 } 391 } 392 ( 393 NetworkAddressTranslator::get_inbound_map_key(m), 394 NetworkAddressTranslator::get_outbound_map_key(m), 395 ) 396 } else { 397 (String::new(), String::new()) 398 } 399 }; 400 401 if expired { 402 { 403 let mut inbound_map = self.inbound_map.lock().await; 404 inbound_map.remove(&in_key); 405 } 406 { 407 let mut outbound_map = self.outbound_map.lock().await; 408 outbound_map.remove(&out_key); 409 } 410 } 411 412 let outbound_map = self.outbound_map.lock().await; 413 outbound_map.get(o_key).map(Arc::clone) 414 } 415 416 // caller must hold the mutex 417 pub(crate) async fn find_inbound_mapping(&self, i_key: &str) -> Option<Arc<Mapping>> { 418 let mut expired = false; 419 let (in_key, out_key) = { 420 let inbound_map = self.inbound_map.lock().await; 421 if let Some(m) = inbound_map.get(i_key) { 422 let now = SystemTime::now(); 423 424 { 425 let expires = m.expires.lock().await; 426 // check if this Mapping is expired 427 if now.duration_since(*expires).is_ok() { 428 expired = true; 429 } 430 } 431 ( 432 NetworkAddressTranslator::get_inbound_map_key(m), 433 NetworkAddressTranslator::get_outbound_map_key(m), 434 ) 435 } else { 436 (String::new(), String::new()) 437 } 438 }; 439 440 if expired { 441 { 442 let mut inbound_map = self.inbound_map.lock().await; 443 inbound_map.remove(&in_key); 444 } 445 { 446 let mut outbound_map = self.outbound_map.lock().await; 447 outbound_map.remove(&out_key); 448 } 449 } 450 451 let inbound_map = self.inbound_map.lock().await; 452 inbound_map.get(i_key).map(Arc::clone) 453 } 454 455 // caller must hold the mutex 456 fn get_outbound_map_key(m: &Mapping) -> String { 457 format!("{}:{}:{}", m.proto, m.local, m.bound) 458 } 459 460 fn get_inbound_map_key(m: &Mapping) -> String { 461 format!("{}:{}", m.proto, m.mapped) 462 } 463 464 async fn inbound_map_len(&self) -> usize { 465 let inbound_map = self.inbound_map.lock().await; 466 inbound_map.len() 467 } 468 469 async fn outbound_map_len(&self) -> usize { 470 let outbound_map = self.outbound_map.lock().await; 471 outbound_map.len() 472 } 473 } 474