Skip to content

Commit

Permalink
⬆️ upgrade surge-ping
Browse files Browse the repository at this point in the history
  • Loading branch information
mokeyish committed Oct 28, 2023
1 parent 9de7f7d commit cf07c81
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 5 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ dist

.idea/

etc/smartdns/smartdns.yaml
etc/smartdns/smartdns.yaml

localhost.crt
localhost.key
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ dns-over-https-rustls = [
# hickory-resolver = { git = "https://github.com/hickory-dns/hickory-dns.git", rev = "41b6e33"}
# hickory-server = { git = "https://github.com/hickory-dns/hickory-dns.git", rev = "41b6e33"}
# rustls-native-certs = { git = "https://github.com/mokeyish/rustls-native-certs.git" }
surge-ping = { git = "https://github.com/mokeyish/surge-ping.git", rev = "04c51d6" }
hostname = { git = "https://github.com/mokeyish/hostname.git", branch = "dev" }
enum_dispatch = { git = "https://gitlab.com/mokeyish/enum_dispatch.git", branch = "master"}

Expand Down Expand Up @@ -90,7 +89,7 @@ rustls-native-certs = "0.6.2"
lru = { version = "0.12", default-features = false}
time = "0.3"
chrono = "0.4"
surge-ping = "0.7.4"
surge-ping = "0.8.0"
rand = "0.8.5"
smallvec = "1.10.0"
csv = "1.1"
Expand Down
137 changes: 135 additions & 2 deletions src/infra/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,129 @@ mod icmp {

use super::{do_agg, PingAddr, PingError, PingOptions, PingOutput};

mod auto_sock_type {
use cfg_if::cfg_if;
use socket2::Type;
use surge_ping::ICMP;

cfg_if! {
if #[cfg(any(target_os = "linux"))] {
use once_cell::sync::Lazy;
use socket2::{Domain, Protocol, Socket};
use std::{io, net::IpAddr};

pub trait CheckAllowUnprivilegedIcmp {
fn allow_unprivileged_icmp(&self) -> bool;
}


pub trait CheckAllowRawSocket {
fn allow_raw_socket(&self) -> bool;
}

impl CheckAllowUnprivilegedIcmp for ICMP {
fn allow_unprivileged_icmp(&self) -> bool {
match self {
ICMP::V4 => *ALLOW_IPV4_UNPRIVILEGED_ICMP,
ICMP::V6 => *ALLOW_IPV6_UNPRIVILEGED_ICMP
}
}
}

impl CheckAllowRawSocket for ICMP {
#[inline]
fn allow_raw_socket(&self) -> bool {
match self {
ICMP::V4 => *ALLOW_IPV4_RAW_SOCKET,
ICMP::V6 => *ALLOW_IPV6_RAW_SOCKET
}
}
}

impl CheckAllowUnprivilegedIcmp for IpAddr {
#[inline]
fn allow_unprivileged_icmp(&self) -> bool {
match self {
IpAddr::V4(_) => *ALLOW_IPV4_UNPRIVILEGED_ICMP,
IpAddr::V6(_) => *ALLOW_IPV6_UNPRIVILEGED_ICMP,
}
}
}

impl CheckAllowRawSocket for IpAddr {
#[inline]
fn allow_raw_socket(&self) -> bool {
match self {
IpAddr::V4(_) => *ALLOW_IPV4_RAW_SOCKET,
IpAddr::V6(_) => *ALLOW_IPV6_RAW_SOCKET,
}
}
}




pub static ALLOW_IPV4_UNPRIVILEGED_ICMP: Lazy<bool> = Lazy::new(|| {
allow_unprivileged_icmp(Domain::IPV4, Protocol::ICMPV4)
});

pub static ALLOW_IPV4_RAW_SOCKET: Lazy<bool> =
Lazy::new(|| allow_raw_socket(Domain::IPV4, Protocol::ICMPV4));


pub static ALLOW_IPV6_UNPRIVILEGED_ICMP: Lazy<bool> = Lazy::new(|| {
allow_unprivileged_icmp(Domain::IPV6, Protocol::ICMPV6)
});

pub static ALLOW_IPV6_RAW_SOCKET: Lazy<bool> =
Lazy::new(|| allow_raw_socket(Domain::IPV6, Protocol::ICMPV6));


fn allow_unprivileged_icmp(domain: Domain, proto: Protocol) -> bool {
!is_permission_denied(Socket::new(domain, Type::DGRAM, Some(proto)))
}

fn allow_raw_socket(domain: Domain, proto: Protocol) -> bool {
!is_permission_denied(Socket::new(domain, Type::RAW, Some(proto)))
}

#[inline]
fn is_permission_denied(res: io::Result<Socket>) -> bool {
matches!(res, Err(err) if matches!(err.kind(), std::io::ErrorKind::PermissionDenied))
}

}


}

#[allow(unused_variables)]
pub fn detect(kind: ICMP) -> Type {
cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "android"))] {

if kind.allow_unprivileged_icmp() {
// enable by running: `sudo sysctl -w net.ipv4.ping_group_range='0 2147483647'`
Type::DGRAM
} else if kind.allow_raw_socket() {
// enable by running: `sudo setcap CAP_NET_RAW+eip /path/to/program`
Type::RAW
} else {
panic!("unpriviledged ping is disabled, please enable by setting `net.ipv4.ping_group_range` or setting `CAP_NET_RAW`")
}
} else if #[cfg(any(target_os = "macos"))] {
// MacOS seems enable UNPRIVILEGED_ICMP by default.
Type::DGRAM
} else if #[cfg(any(target_os = "windows"))] {
// Windows seems enable RAW_SOCKET by default.
Type::RAW
} else {
Type::RAW
}
}
}
}

pub async fn ping(ipaddr: IpAddr, opts: PingOptions) -> Result<PingOutput, PingError> {
let PingOptions {
times,
Expand All @@ -300,8 +423,18 @@ mod icmp {
let mut durations = Vec::new();

let client = match ipaddr {
IpAddr::V4(_) => Client::new(&Config::default()),
IpAddr::V6(_) => Client::new(&Config::builder().kind(ICMP::V6).build()),
IpAddr::V4(_) => Client::new(
&Config::builder()
.kind(ICMP::V4)
.sock_type_hint(auto_sock_type::detect(ICMP::V4))
.build(),
),
IpAddr::V6(_) => Client::new(
&Config::builder()
.kind(ICMP::V6)
.sock_type_hint(auto_sock_type::detect(ICMP::V6))
.build(),
),
}?;

let mut pinger = client.pinger(ipaddr, PingIdentifier(random())).await;
Expand Down

0 comments on commit cf07c81

Please sign in to comment.