Improved port forwarding on quirky routers

pull/46/head
Dennis Schwerdel 2019-12-22 22:51:40 +01:00
parent ed81c0de88
commit 10ebd08dad
2 changed files with 68 additions and 42 deletions

View File

@ -2,6 +2,11 @@
This project follows [semantic versioning](http://semver.org). This project follows [semantic versioning](http://semver.org).
### Unreleased
- [changed] Improved port forwarding on quirky routers
### v1.2.1 (2019-12-22) ### v1.2.1 (2019-12-22)
- [fixed] Fixed a problem with service restrictions - [fixed] Fixed a problem with service restrictions

View File

@ -4,7 +4,7 @@
use std::{io, net::SocketAddrV4}; use std::{io, net::SocketAddrV4};
use igd::*; use igd::{search_gateway, AddAnyPortError, AddPortError, Gateway, PortMappingProtocol, SearchError};
use super::util::{get_internal_ip, SystemTimeSource, Time, TimeSource}; use super::util::{get_internal_ip, SystemTimeSource, Time, TimeSource};
@ -46,54 +46,75 @@ impl PortForwarding {
return None return None
} }
}; };
// Try to activate the port forwarding if let Ok((port, timeout)) = Self::get_any_forwarding(&gateway, internal_addr, port) {
// - First with external port = internal port and timeout info!("Port-forwarding: external IP is {}", external_ip);
// - If the port is used, request any port let external_addr = SocketAddrV4::new(external_ip, port);
// - If timeout is denied, try permanent forwarding info!("Port-forwarding: sucessfully activated port forward on {}, timeout: {}", external_addr, timeout);
info!("Port-forwarding: external IP is {}", external_ip); let next_extension =
let (external_addr, timeout) = match gateway.add_port( if timeout > 0 { Some(SystemTimeSource::now() + Time::from(timeout) - 60) } else { None };
PortMappingProtocol::UDP, Some(PortForwarding { internal_addr, external_addr, gateway, next_extension })
internal_addr.port(), } else {
internal_addr, None
LEASE_TIME, }
DESCRIPTION }
) {
Ok(()) => (SocketAddrV4::new(external_ip, internal_addr.port()), LEASE_TIME), fn get_any_forwarding(gateway: &Gateway, addr: SocketAddrV4, port: u16) -> Result<(u16, u32), ()> {
Err(AddPortError::PortInUse) => { if let Ok(a) = Self::get_forwarding(gateway, addr, port) {
match gateway.add_any_port(PortMappingProtocol::UDP, internal_addr, LEASE_TIME, DESCRIPTION) { return Ok(a)
Ok(port) => (SocketAddrV4::new(external_ip, port), LEASE_TIME), }
Err(AddAnyPortError::OnlyPermanentLeasesSupported) => { if let Ok(a) = Self::get_forwarding(gateway, addr, 0) {
match gateway.add_any_port(PortMappingProtocol::UDP, internal_addr, 0, DESCRIPTION) { return Ok(a)
Ok(port) => (SocketAddrV4::new(external_ip, port), 0), }
Err(err) => { for i in 1..5 {
error!("Port-forwarding: failed to activate port forwarding: {}", err); if let Ok(a) = Self::get_forwarding(gateway, addr, port + i) {
return None return Ok(a)
} }
}
for _ in 0..5 {
if let Ok(a) = Self::get_forwarding(gateway, addr, rand::random()) {
return Ok(a)
}
}
Err(())
}
fn get_forwarding(gateway: &Gateway, addr: SocketAddrV4, port: u16) -> Result<(u16, u32), ()> {
info!("Trying external port {}", port);
if port == 0 {
match gateway.add_any_port(PortMappingProtocol::UDP, addr, LEASE_TIME, DESCRIPTION) {
Ok(port) => Ok((port, LEASE_TIME)),
Err(AddAnyPortError::OnlyPermanentLeasesSupported) => {
match gateway.add_any_port(PortMappingProtocol::UDP, addr, 0, DESCRIPTION) {
Ok(port) => Ok((port, 0)),
Err(err) => {
error!("Port-forwarding: failed to activate port forwarding: {}", err);
Err(())
} }
} }
Err(err) => { }
error!("Port-forwarding: failed to activate port forwarding: {}", err); Err(err) => {
return None error!("Port-forwarding: failed to activate port forwarding: {}", err);
} Err(())
} }
} }
Err(AddPortError::OnlyPermanentLeasesSupported) => { } else {
match gateway.add_port(PortMappingProtocol::UDP, internal_addr.port(), internal_addr, 0, DESCRIPTION) { match gateway.add_port(PortMappingProtocol::UDP, port, addr, LEASE_TIME, DESCRIPTION) {
Ok(()) => (SocketAddrV4::new(external_ip, internal_addr.port()), 0), Ok(()) => Ok((port, LEASE_TIME)),
Err(err) => { Err(AddPortError::OnlyPermanentLeasesSupported) => {
error!("Port-forwarding: failed to activate port forwarding: {}", err); match gateway.add_port(PortMappingProtocol::UDP, port, addr, 0, DESCRIPTION) {
return None Ok(()) => Ok((port, 0)),
Err(err) => {
error!("Port-forwarding: failed to activate port forwarding: {}", err);
Err(())
}
} }
} }
Err(err) => {
error!("Port-forwarding: failed to activate port forwarding: {}", err);
Err(())
}
} }
Err(err) => { }
error!("Port-forwarding: failed to activate port forwarding: {}", err);
return None
}
};
info!("Port-forwarding: sucessfully activated port forward on {}, timeout: {}", external_addr, timeout);
let next_extension = if timeout > 0 { Some(SystemTimeSource::now() + Time::from(timeout) - 60) } else { None };
Some(PortForwarding { internal_addr, external_addr, gateway, next_extension })
} }
pub fn check_extend(&mut self) { pub fn check_extend(&mut self) {