public IP address autodiscovery #20
4 changed files with 36 additions and 23 deletions
|
@ -5,7 +5,8 @@ mod runtime;
|
||||||
|
|
||||||
pub use options::{ConfigOpts, ConfigOptsAcme, ConfigOptsBase, ConfigOptsConsul};
|
pub use options::{ConfigOpts, ConfigOptsAcme, ConfigOptsBase, ConfigOptsConsul};
|
||||||
pub use runtime::{
|
pub use runtime::{
|
||||||
RuntimeConfig, RuntimeConfigAcme, RuntimeConfigConsul, RuntimeConfigFirewall, RuntimeConfigIgd, RuntimeConfigStun
|
RuntimeConfig, RuntimeConfigAcme, RuntimeConfigConsul, RuntimeConfigFirewall, RuntimeConfigIgd,
|
||||||
|
RuntimeConfigStun,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const EXPIRATION_TIME: u16 = 300;
|
pub const EXPIRATION_TIME: u16 = 300;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::time::Duration;
|
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
|
|
||||||
|
@ -165,7 +165,12 @@ impl RuntimeConfigStun {
|
||||||
pub(super) fn new(opts: &ConfigOptsBase) -> Result<Self> {
|
pub(super) fn new(opts: &ConfigOptsBase) -> Result<Self> {
|
||||||
let mut stun_server_v4 = None;
|
let mut stun_server_v4 = None;
|
||||||
let mut stun_server_v6 = None;
|
let mut stun_server_v6 = None;
|
||||||
for addr in opts.stun_server.as_deref().unwrap_or(super::STUN_SERVER).to_socket_addrs()? {
|
for addr in opts
|
||||||
|
.stun_server
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or(super::STUN_SERVER)
|
||||||
|
.to_socket_addrs()?
|
||||||
|
{
|
||||||
if addr.is_ipv4() {
|
if addr.is_ipv4() {
|
||||||
stun_server_v4 = Some(addr);
|
stun_server_v4 = Some(addr);
|
||||||
}
|
}
|
||||||
|
@ -177,8 +182,10 @@ impl RuntimeConfigStun {
|
||||||
let refresh_time = Duration::from_secs(opts.refresh_time.unwrap_or(super::REFRESH_TIME).into());
|
let refresh_time = Duration::from_secs(opts.refresh_time.unwrap_or(super::REFRESH_TIME).into());
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
stun_server_v4: stun_server_v4.ok_or(anyhow!("Unable to resolve STUN server's IPv4 address"))?,
|
stun_server_v4: stun_server_v4
|
||||||
stun_server_v6: stun_server_v6.ok_or(anyhow!("Unable to resolve STUN server's IPv6 address"))?,
|
.ok_or(anyhow!("Unable to resolve STUN server's IPv4 address"))?,
|
||||||
|
stun_server_v6: stun_server_v6
|
||||||
|
.ok_or(anyhow!("Unable to resolve STUN server's IPv6 address"))?,
|
||||||
refresh_time,
|
refresh_time,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,7 @@ impl Diplonat {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let sa = StunActor::new(
|
let sa = StunActor::new(&rt_cfg.consul, &rt_cfg.stun, &rt_cfg.consul.node_name);
|
||||||
&rt_cfg.consul,
|
|
||||||
&rt_cfg.stun,
|
|
||||||
&rt_cfg.consul.node_name,
|
|
||||||
);
|
|
||||||
|
|
||||||
let ctx = Self {
|
let ctx = Self {
|
||||||
consul: ca,
|
consul: ca,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::net::{SocketAddr, IpAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
use anyhow::{Result, bail, anyhow};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use log::*;
|
use log::*;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::config::{RuntimeConfigConsul, RuntimeConfigStun};
|
use crate::config::{RuntimeConfigConsul, RuntimeConfigStun};
|
||||||
use crate::consul;
|
use crate::consul;
|
||||||
|
@ -23,7 +23,11 @@ pub struct AutodiscoverResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StunActor {
|
impl StunActor {
|
||||||
pub fn new(consul_config: &RuntimeConfigConsul, stun_config: &RuntimeConfigStun, node: &str) -> Self {
|
pub fn new(
|
||||||
|
consul_config: &RuntimeConfigConsul,
|
||||||
|
stun_config: &RuntimeConfigStun,
|
||||||
|
node: &str,
|
||||||
|
) -> Self {
|
||||||
assert!(stun_config.stun_server_v4.is_ipv4());
|
assert!(stun_config.stun_server_v4.is_ipv4());
|
||||||
assert!(stun_config.stun_server_v6.is_ipv6());
|
assert!(stun_config.stun_server_v6.is_ipv6());
|
||||||
|
|
||||||
|
@ -67,10 +71,18 @@ impl StunActor {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.consul.kv_put(&consul_key, serde_json::to_vec(&AutodiscoverResult{
|
self
|
||||||
timestamp: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_secs(),
|
.consul
|
||||||
address: discovered_addr,
|
.kv_put(
|
||||||
})?).await?;
|
&consul_key,
|
||||||
|
serde_json::to_vec(&AutodiscoverResult {
|
||||||
|
timestamp: SystemTime::now()
|
||||||
|
.duration_since(SystemTime::UNIX_EPOCH)?
|
||||||
|
.as_secs(),
|
||||||
|
address: discovered_addr,
|
||||||
|
})?,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -80,16 +92,13 @@ async fn get_mapped_addr(stun_server: SocketAddr, binding_addr: SocketAddr) -> R
|
||||||
use stun_client::*;
|
use stun_client::*;
|
||||||
|
|
||||||
let mut client = Client::new(binding_addr, None).await.unwrap();
|
let mut client = Client::new(binding_addr, None).await.unwrap();
|
||||||
let res = client
|
let res = client.binding_request(stun_server, None).await.unwrap();
|
||||||
.binding_request(stun_server, None)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if res.get_class() != Class::SuccessResponse {
|
if res.get_class() != Class::SuccessResponse {
|
||||||
bail!("STUN server did not responde with a success response");
|
bail!("STUN server did not responde with a success response");
|
||||||
}
|
}
|
||||||
|
|
||||||
let xor_mapped_addr = Attribute::get_xor_mapped_address(&res)
|
let xor_mapped_addr = Attribute::get_xor_mapped_address(&res)
|
||||||
.ok_or(anyhow!("no XorMappedAddress found in STUN response"))?;
|
.ok_or(anyhow!("no XorMappedAddress found in STUN response"))?;
|
||||||
Ok(xor_mapped_addr)
|
Ok(xor_mapped_addr)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue