public IP address autodiscovery #20

Merged
lx merged 10 commits from stun into main 2023-04-21 09:56:22 +00:00
5 changed files with 25 additions and 24 deletions
Showing only changes of commit f410230240 - Show all commits

View file

@ -26,7 +26,7 @@ fn all_valid_options() -> HashMap<String, String> {
);
opts.insert(
"DIPLONAT_PRIVATE_IP".to_string(),
"172.123.43.555".to_string(),
"172.123.43.55".to_string(),
);
opts.insert("DIPLONAT_REFRESH_TIME".to_string(), "10".to_string());
opts.insert(
@ -118,7 +118,7 @@ fn ok_from_iter_all_valid_options() {
);
assert_eq!(rt_config.firewall.refresh_time, refresh_time);
assert_eq!(
&rt_config.igd.private_ip.unwrap(),
&rt_config.igd.private_ip.unwrap().to_string(),
opts.get(&"DIPLONAT_PRIVATE_IP".to_string()).unwrap()
);
assert_eq!(rt_config.igd.expiration_time, expiration_time);

View file

@ -1,9 +1,9 @@
use std::fs::File;
use std::io::Read;
use std::net::{SocketAddr, ToSocketAddrs};
use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
use std::time::Duration;
use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, bail, Context, Result};
use crate::config::{ConfigOpts, ConfigOptsAcme, ConfigOptsBase, ConfigOptsConsul};
@ -31,7 +31,7 @@ pub struct RuntimeConfigFirewall {
#[derive(Debug)]
pub struct RuntimeConfigIgd {
pub private_ip: Option<String>,
pub private_ip: Option<Ipv4Addr>,
pub expiration_time: Duration,
pub refresh_time: Duration,
}
@ -137,7 +137,12 @@ impl RuntimeConfigFirewall {
impl RuntimeConfigIgd {
pub(super) fn new(opts: &ConfigOptsBase) -> Result<Self> {
let private_ip = opts.private_ip.clone();
let private_ip = opts
.private_ip
.as_ref()
.map(|x| x.parse())
.transpose()
.context("parse private_ip")?;
let expiration_time = Duration::from_secs(
opts.expiration_time
.unwrap_or(super::EXPIRATION_TIME)

View file

@ -23,7 +23,7 @@ impl Diplonat {
let fw = FirewallActor::new(rt_cfg.firewall.refresh_time, &ca.rx_open_ports).await?;
let ia = IgdActor::new(
rt_cfg.igd.private_ip.as_ref().map(String::as_str),
rt_cfg.igd.private_ip,
rt_cfg.igd.refresh_time,
rt_cfg.igd.expiration_time,
&ca.rx_open_ports,

View file

@ -11,7 +11,7 @@ pub fn setup(ipt: &iptables::IPTables) -> Result<()> {
// ensure we start from a clean state without any rule already set
cleanup(ipt)?;
info!("{}: creating DIPLONAT chain using", ipt.cmd);
info!("{}: creating DIPLONAT chain", ipt.cmd);
ipt.new_chain("filter", "DIPLONAT")
.context("Failed to create new chain")?;
ipt.insert_unique("filter", "INPUT", "-j DIPLONAT", 1)

View file

@ -1,4 +1,4 @@
use std::net::SocketAddrV4;
use std::net::{Ipv4Addr, SocketAddrV4};
use anyhow::{Context, Result};
use igd::{aio::*, PortMappingProtocol};
@ -17,12 +17,12 @@ pub struct IgdActor {
gateway: Gateway,
refresh: Duration,
expire: Duration,
private_ip: String,
private_ip: Ipv4Addr,
}
impl IgdActor {
pub async fn new(
priv_ip: Option<&str>,
priv_ip: Option<Ipv4Addr>,
refresh: Duration,
expire: Duration,
rxp: &watch::Receiver<messages::PublicExposedPorts>,
@ -34,7 +34,7 @@ impl IgdActor {
let private_ip = if let Some(ip) = priv_ip {
info!("Using private IP from config: {}", ip);
ip.to_string()
ip
} else {
info!("Trying to automatically detect private IP");
let gwa = gw.addr.ip().octets();
@ -47,18 +47,17 @@ impl IgdActor {
),
};
#[allow(unused_parens)]
let public_ip = get_if_addrs::get_if_addrs()?
let private_ip = get_if_addrs::get_if_addrs()?
.into_iter()
.map(|i| i.addr.ip())
.filter(|a| match a {
std::net::IpAddr::V4(a4) => (a4.octets()[..cmplen] == gwa[..cmplen]),
_ => false,
.filter_map(|a| match a {
std::net::IpAddr::V4(a4) if a4.octets()[..cmplen] == gwa[..cmplen] => Some(a4),
_ => None,
})
.next()
.expect("No interface has an IP on same subnet as gateway")
.to_string();
info!("Found private IP: {}", public_ip);
public_ip
.expect("No interface has an IP on same subnet as gateway");
info!("Autodetected private IP: {}", private_ip);
private_ip
};
let ctx = Self {
@ -104,10 +103,7 @@ impl IgdActor {
for (proto, list) in actions.iter() {
for port in *list {
let service_str = format!("{}:{}", self.private_ip, port);
let service = service_str
.parse::<SocketAddrV4>()
.context("Invalid socket address")?;
let service = SocketAddrV4::new(self.private_ip, *port);
self.gateway
.add_port(
*proto,