diff --git a/clash/src/main.rs b/clash/src/main.rs index 4ceb3e433..e0bc4a467 100644 --- a/clash/src/main.rs +++ b/clash/src/main.rs @@ -2,7 +2,7 @@ extern crate clash_lib as clash; use clap::Parser; use clash::TokioRuntime; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; #[derive(Parser)] #[clap(author, version, about, long_about = None)] @@ -25,15 +25,20 @@ struct Cli { fn main() { let cli = Cli::parse(); + let file = cli + .directory + .as_ref() + .unwrap_or(&std::env::current_dir().unwrap()) + .join(cli.config) + .to_string_lossy() + .to_string(); + + if !Path::new(&file).exists() { + panic!("config file not found: {}", file); + } + clash::start(clash::Options { - config: clash::Config::File( - cli.directory - .as_ref() - .unwrap_or(&std::env::current_dir().unwrap()) - .join(cli.config) - .to_string_lossy() - .to_string(), - ), + config: clash::Config::File(file), cwd: cli.directory.map(|x| x.to_string_lossy().to_string()), rt: Some(TokioRuntime::MultiThread), }) diff --git a/clash_lib/src/app/dispatcher/mod.rs b/clash_lib/src/app/dispatcher/mod.rs index 7e725ae8b..b3e36e0a9 100644 --- a/clash_lib/src/app/dispatcher/mod.rs +++ b/clash_lib/src/app/dispatcher/mod.rs @@ -4,7 +4,10 @@ mod tracked; pub use dispatcher::Dispatcher; pub use statistics_manager::Manager as StatisticsManager; +pub use tracked::BoxedChainedDatagram; pub use tracked::BoxedChainedStream; +pub use tracked::ChainedDatagram; +pub use tracked::ChainedDatagramWrapper; pub use tracked::ChainedStream; pub use tracked::ChainedStreamWrapper; pub use tracked::TrackedDatagram; diff --git a/clash_lib/src/app/dispatcher/tracked.rs b/clash_lib/src/app/dispatcher/tracked.rs index fcad977a4..560fb54a4 100644 --- a/clash_lib/src/app/dispatcher/tracked.rs +++ b/clash_lib/src/app/dispatcher/tracked.rs @@ -10,7 +10,7 @@ use tracing::debug; use crate::{ app::router::RuleMatcher, - proxy::{datagram::UdpPacket, AnyOutboundDatagram, ProxyStream}, + proxy::{datagram::UdpPacket, OutboundDatagram, ProxyStream}, session::Session, }; @@ -263,8 +263,92 @@ impl AsyncWrite for TrackedStream { } } +#[async_trait::async_trait] +pub trait ChainedDatagram: + OutboundDatagram +{ + fn chain(&self) -> &ProxyChain; + async fn append_to_chain(&self, name: &str); +} + +pub type BoxedChainedDatagram = Box; + +#[async_trait::async_trait] +impl ChainedDatagram for ChainedDatagramWrapper +where + T: Sink + Unpin + Send + Sync + 'static, + T: Stream, +{ + fn chain(&self) -> &ProxyChain { + &self.chain + } + + async fn append_to_chain(&self, name: &str) { + self.chain.push(name.to_owned()).await; + } +} + +#[derive(Debug)] +pub struct ChainedDatagramWrapper { + inner: T, + chain: ProxyChain, +} + +impl ChainedDatagramWrapper { + pub fn new(inner: T) -> Self { + Self { + inner, + chain: ProxyChain::default(), + } + } +} + +impl Stream for ChainedDatagramWrapper +where + T: Stream + Unpin, +{ + type Item = UdpPacket; + + fn poll_next( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.get_mut().inner).poll_next(cx) + } +} +impl Sink for ChainedDatagramWrapper +where + T: Sink + Unpin, +{ + type Error = std::io::Error; + fn poll_ready( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.get_mut().inner).poll_ready(cx) + } + + fn start_send(self: Pin<&mut Self>, item: UdpPacket) -> Result<(), Self::Error> { + Pin::new(&mut self.get_mut().inner).start_send(item) + } + + fn poll_flush( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.get_mut().inner).poll_flush(cx) + } + + fn poll_close( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll> { + Pin::new(&mut self.get_mut().inner).poll_close(cx) + } +} + pub struct TrackedDatagram { - inner: AnyOutboundDatagram, + inner: BoxedChainedDatagram, manager: Arc, tracker: Arc, close_notify: Receiver<()>, @@ -272,12 +356,13 @@ pub struct TrackedDatagram { impl TrackedDatagram { pub async fn new( - inner: AnyOutboundDatagram, + inner: BoxedChainedDatagram, manager: Arc, sess: Session, rule: Option<&Box>, ) -> Self { let uuid = uuid::Uuid::new_v4(); + let chain = inner.chain().clone(); let (tx, rx) = tokio::sync::oneshot::channel(); let s = Self { inner, @@ -292,6 +377,7 @@ impl TrackedDatagram { .map(|x| x.type_name().to_owned()) .unwrap_or_default(), rule_payload: rule.map(|x| x.payload().to_owned()).unwrap_or_default(), + proxy_chain_holder: chain.clone(), ..Default::default() }), close_notify: rx, diff --git a/clash_lib/src/proxy/direct/mod.rs b/clash_lib/src/proxy/direct/mod.rs index 19f432a13..b18f74356 100644 --- a/clash_lib/src/proxy/direct/mod.rs +++ b/clash_lib/src/proxy/direct/mod.rs @@ -1,9 +1,12 @@ -use crate::app::dispatcher::{BoxedChainedStream, ChainedStream, ChainedStreamWrapper}; +use crate::app::dispatcher::{ + BoxedChainedDatagram, BoxedChainedStream, ChainedDatagram, ChainedDatagramWrapper, + ChainedStream, ChainedStreamWrapper, +}; use crate::app::dns::ThreadSafeDNSResolver; use crate::config::internal::proxy::PROXY_DIRECT; use crate::proxy::datagram::OutboundDatagramImpl; use crate::proxy::utils::{new_tcp_stream, new_udp_socket}; -use crate::proxy::{AnyOutboundDatagram, AnyOutboundHandler, AnyStream, OutboundHandler}; +use crate::proxy::{AnyOutboundHandler, AnyStream, OutboundHandler}; use crate::session::{Session, SocksAddr}; use async_trait::async_trait; @@ -72,14 +75,18 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> std::io::Result { - new_udp_socket( + ) -> std::io::Result { + let d = new_udp_socket( None, sess.iface.as_ref(), #[cfg(any(target_os = "linux", target_os = "android"))] None, ) .await - .map(|x| OutboundDatagramImpl::new(x, resolver)) + .map(|x| OutboundDatagramImpl::new(x, resolver))?; + + let d = ChainedDatagramWrapper::new(d); + d.append_to_chain(self.name()).await; + Ok(Box::new(d)) } } diff --git a/clash_lib/src/proxy/fallback/mod.rs b/clash_lib/src/proxy/fallback/mod.rs index e2fac8053..7e8449879 100644 --- a/clash_lib/src/proxy/fallback/mod.rs +++ b/clash_lib/src/proxy/fallback/mod.rs @@ -5,7 +5,7 @@ use tracing::debug; use crate::{ app::{ - dispatcher::BoxedChainedStream, + dispatcher::{BoxedChainedDatagram, BoxedChainedStream}, dns::ThreadSafeDNSResolver, remote_content_manager::{ providers::proxy_provider::proxy_provider::ThreadSafeProxyProvider, ProxyManager, @@ -15,8 +15,8 @@ use crate::{ }; use super::{ - utils::provider_helper::get_proxies_from_providers, AnyOutboundDatagram, AnyOutboundHandler, - AnyStream, CommonOption, OutboundHandler, OutboundType, + utils::provider_helper::get_proxies_from_providers, AnyOutboundHandler, AnyStream, + CommonOption, OutboundHandler, OutboundType, }; #[derive(Default, Clone)] @@ -117,7 +117,7 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { let proxy = self.find_alive_proxy(true).await; proxy.connect_datagram(sess, resolver).await } diff --git a/clash_lib/src/proxy/loadbalance/mod.rs b/clash_lib/src/proxy/loadbalance/mod.rs index fb606b986..ee7ee11aa 100644 --- a/clash_lib/src/proxy/loadbalance/mod.rs +++ b/clash_lib/src/proxy/loadbalance/mod.rs @@ -8,7 +8,8 @@ use tracing::debug; use crate::{ app::{ - dispatcher::BoxedChainedStream, dns::ThreadSafeDNSResolver, + dispatcher::{BoxedChainedDatagram, BoxedChainedStream}, + dns::ThreadSafeDNSResolver, remote_content_manager::providers::proxy_provider::ThreadSafeProxyProvider, }, config::internal::proxy::LoadBalanceStrategy, @@ -18,8 +19,8 @@ use crate::{ use self::helpers::{strategy_consistent_hashring, strategy_rr, StrategyFn}; use super::{ - utils::provider_helper::get_proxies_from_providers, AnyOutboundDatagram, AnyOutboundHandler, - AnyStream, CommonOption, OutboundHandler, OutboundType, + utils::provider_helper::get_proxies_from_providers, AnyOutboundHandler, AnyStream, + CommonOption, OutboundHandler, OutboundType, }; #[derive(Default, Clone)] @@ -121,7 +122,7 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { let proxies = self.get_proxies(false).await; let proxy = (self.inner.lock().await.strategy_fn)(proxies, &sess).await?; debug!("{} use proxy {}", self.name(), proxy.name()); diff --git a/clash_lib/src/proxy/mocks.rs b/clash_lib/src/proxy/mocks.rs index e442797c7..b0a6404a5 100644 --- a/clash_lib/src/proxy/mocks.rs +++ b/clash_lib/src/proxy/mocks.rs @@ -5,7 +5,7 @@ use mockall::mock; use crate::{ app::{ - dispatcher::BoxedChainedStream, + dispatcher::{BoxedChainedDatagram, BoxedChainedStream}, dns::ThreadSafeDNSResolver, remote_content_manager::providers::{ proxy_provider::ProxyProvider, Provider, ProviderType, ProviderVehicleType, @@ -14,7 +14,7 @@ use crate::{ session::{Session, SocksAddr}, }; -use super::{AnyOutboundDatagram, AnyOutboundHandler, AnyStream, OutboundHandler, OutboundType}; +use super::{AnyOutboundHandler, AnyStream, OutboundHandler, OutboundType}; mock! { pub DummyProxyProvider {} @@ -77,7 +77,7 @@ mock! { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result; + ) -> io::Result; /// for API async fn as_map(&self) -> HashMap>; diff --git a/clash_lib/src/proxy/mod.rs b/clash_lib/src/proxy/mod.rs index 7e10e2d95..9c9de4721 100644 --- a/clash_lib/src/proxy/mod.rs +++ b/clash_lib/src/proxy/mod.rs @@ -1,4 +1,4 @@ -use crate::app::dispatcher::BoxedChainedStream; +use crate::app::dispatcher::{BoxedChainedDatagram, BoxedChainedStream}; use crate::app::dns::ThreadSafeDNSResolver; use crate::proxy::datagram::UdpPacket; use crate::proxy::utils::Interface; @@ -91,21 +91,6 @@ impl OutboundDatagram for T where pub type AnyOutboundDatagram = Box>; -#[async_trait] -pub trait OutboundDatagramRecvHalf: Sync + Send + Unpin { - /// Receives a message on the socket. On success, returns the number of - /// bytes read and the origin of the message. - async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocksAddr)>; -} - -/// The send half. -#[async_trait] -pub trait OutboundDatagramSendHalf: Sync + Send + Unpin { - /// Sends a message on the socket to `dst_addr`. On success, returns the - /// number of bytes sent. - async fn send_to(&mut self, buf: &[u8], dst_addr: &SocksAddr) -> io::Result; -} - #[derive(Default, Debug, Clone)] pub struct CommonOption { #[allow(dead_code)] @@ -178,7 +163,7 @@ pub trait OutboundHandler: Sync + Send + Unpin { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result; + ) -> io::Result; /// for API /// the map only contains basic information diff --git a/clash_lib/src/proxy/reject/mod.rs b/clash_lib/src/proxy/reject/mod.rs index d7df2de28..b96bb31d4 100644 --- a/clash_lib/src/proxy/reject/mod.rs +++ b/clash_lib/src/proxy/reject/mod.rs @@ -1,7 +1,7 @@ -use crate::app::dispatcher::BoxedChainedStream; +use crate::app::dispatcher::{BoxedChainedDatagram, BoxedChainedStream}; use crate::app::dns::ThreadSafeDNSResolver; use crate::config::internal::proxy::PROXY_REJECT; -use crate::proxy::{AnyOutboundDatagram, AnyOutboundHandler, AnyStream, OutboundHandler}; +use crate::proxy::{AnyOutboundHandler, AnyStream, OutboundHandler}; use crate::session::{Session, SocksAddr}; use async_trait::async_trait; use serde::Serialize; @@ -58,7 +58,7 @@ impl OutboundHandler for Handler { &self, #[allow(unused_variables)] sess: &Session, #[allow(unused_variables)] _resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { Err(io::Error::new(io::ErrorKind::Other, "REJECT")) } } diff --git a/clash_lib/src/proxy/relay/mod.rs b/clash_lib/src/proxy/relay/mod.rs index 25ad551d0..1af3217e6 100644 --- a/clash_lib/src/proxy/relay/mod.rs +++ b/clash_lib/src/proxy/relay/mod.rs @@ -6,7 +6,9 @@ use futures::stream::{self, StreamExt}; use crate::{ app::{ - dispatcher::{BoxedChainedStream, ChainedStream, ChainedStreamWrapper}, + dispatcher::{ + BoxedChainedDatagram, BoxedChainedStream, ChainedStream, ChainedStreamWrapper, + }, dns::ThreadSafeDNSResolver, remote_content_manager::providers::proxy_provider::ThreadSafeProxyProvider, }, @@ -16,8 +18,8 @@ use crate::{ }; use super::{ - utils::provider_helper::get_proxies_from_providers, AnyOutboundDatagram, AnyOutboundHandler, - AnyStream, CommonOption, OutboundHandler, OutboundType, + utils::provider_helper::get_proxies_from_providers, AnyOutboundHandler, AnyStream, + CommonOption, OutboundHandler, OutboundType, }; #[derive(Default)] @@ -130,7 +132,7 @@ impl OutboundHandler for Handler { &self, _sess: &Session, _resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { Err(new_io_error("not implemented for Relay")) } diff --git a/clash_lib/src/proxy/selector/mod.rs b/clash_lib/src/proxy/selector/mod.rs index 8e5f7fb8f..9aa2b65f0 100644 --- a/clash_lib/src/proxy/selector/mod.rs +++ b/clash_lib/src/proxy/selector/mod.rs @@ -7,7 +7,8 @@ use tracing::debug; use crate::{ app::{ - dispatcher::BoxedChainedStream, dns::ThreadSafeDNSResolver, + dispatcher::{BoxedChainedDatagram, BoxedChainedStream}, + dns::ThreadSafeDNSResolver, remote_content_manager::providers::proxy_provider::ThreadSafeProxyProvider, }, p_debug, @@ -16,8 +17,8 @@ use crate::{ }; use super::{ - utils::provider_helper::get_proxies_from_providers, AnyOutboundDatagram, AnyOutboundHandler, - AnyStream, CommonOption, OutboundHandler, OutboundType, + utils::provider_helper::get_proxies_from_providers, AnyOutboundHandler, AnyStream, + CommonOption, OutboundHandler, OutboundType, }; #[async_trait] @@ -150,7 +151,7 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { self.selected_proxy(true) .await .connect_datagram(sess, resolver) diff --git a/clash_lib/src/proxy/shadowsocks/mod.rs b/clash_lib/src/proxy/shadowsocks/mod.rs index f81ff5a5a..d21c3170b 100644 --- a/clash_lib/src/proxy/shadowsocks/mod.rs +++ b/clash_lib/src/proxy/shadowsocks/mod.rs @@ -12,7 +12,10 @@ use shadowsocks::{ use crate::{ app::{ - dispatcher::{BoxedChainedStream, ChainedStream, ChainedStreamWrapper}, + dispatcher::{ + BoxedChainedDatagram, BoxedChainedStream, ChainedDatagram, ChainedDatagramWrapper, + ChainedStream, ChainedStreamWrapper, + }, dns::ThreadSafeDNSResolver, }, proxy::{CommonOption, OutboundHandler}, @@ -25,7 +28,7 @@ use self::{datagram::OutboundDatagramShadowsocks, stream::ShadowSocksStream}; use super::{ utils::{new_tcp_stream, new_udp_socket}, - AnyOutboundDatagram, AnyOutboundHandler, AnyStream, OutboundType, + AnyOutboundHandler, AnyStream, OutboundType, }; pub enum SimpleOBFSMode { @@ -246,7 +249,7 @@ impl OutboundHandler for Handler { &self, #[allow(unused_variables)] sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { let ctx = Context::new_shared(ServerType::Local); let cfg = ServerConfig::new( (self.opts.server.to_owned(), self.opts.port), @@ -266,11 +269,13 @@ impl OutboundHandler for Handler { ) .await?; let socket = ProxySocket::from_socket(UdpSocketType::Client, ctx, &cfg, socket); - Ok(OutboundDatagramShadowsocks::new( + let d = OutboundDatagramShadowsocks::new( socket, (self.opts.server.to_owned(), self.opts.port), resolver, - ) - .into()) + ); + let d = ChainedDatagramWrapper::new(d); + d.append_to_chain(self.name()).await; + Ok(Box::new(d)) } } diff --git a/clash_lib/src/proxy/trojan/mod.rs b/clash_lib/src/proxy/trojan/mod.rs index e1697b3a8..42256317f 100644 --- a/clash_lib/src/proxy/trojan/mod.rs +++ b/clash_lib/src/proxy/trojan/mod.rs @@ -8,6 +8,9 @@ use sha2::Digest; use sha2::Sha224; use tokio::io::AsyncWriteExt; +use crate::app::dispatcher::BoxedChainedDatagram; +use crate::app::dispatcher::ChainedDatagram; +use crate::app::dispatcher::ChainedDatagramWrapper; use crate::app::dispatcher::ChainedStream; use crate::app::dispatcher::ChainedStreamWrapper; use crate::common::utils; @@ -23,8 +26,7 @@ use super::transport::TLSOptions; use super::{ options::{GrpcOption, WsOption}, utils::new_tcp_stream, - AnyOutboundDatagram, AnyOutboundHandler, AnyStream, CommonOption, OutboundHandler, - OutboundType, + AnyOutboundHandler, AnyStream, CommonOption, OutboundHandler, OutboundType, }; mod datagram; @@ -157,7 +159,7 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { let stream = new_tcp_stream( resolver.clone(), self.opts.server.as_str(), @@ -179,9 +181,10 @@ impl OutboundHandler for Handler { let stream = self.inner_proxy_stream(stream, sess, false).await?; - Ok(Box::new(OutboundDatagramTrojan::new( - stream, - sess.destination.clone(), - ))) + let d = OutboundDatagramTrojan::new(stream, sess.destination.clone()); + + let chained = ChainedDatagramWrapper::new(d); + chained.append_to_chain(self.name()).await; + Ok(Box::new(chained)) } } diff --git a/clash_lib/src/proxy/urltest/mod.rs b/clash_lib/src/proxy/urltest/mod.rs index 054d48a76..bc43371ed 100644 --- a/clash_lib/src/proxy/urltest/mod.rs +++ b/clash_lib/src/proxy/urltest/mod.rs @@ -6,7 +6,7 @@ use tracing::debug; use crate::{ app::{ - dispatcher::BoxedChainedStream, + dispatcher::{BoxedChainedDatagram, BoxedChainedStream}, dns::ThreadSafeDNSResolver, remote_content_manager::{ providers::proxy_provider::ThreadSafeProxyProvider, ProxyManager, @@ -17,8 +17,8 @@ use crate::{ }; use super::{ - utils::provider_helper::get_proxies_from_providers, AnyOutboundDatagram, AnyOutboundHandler, - AnyStream, CommonOption, OutboundHandler, OutboundType, + utils::provider_helper::get_proxies_from_providers, AnyOutboundHandler, AnyStream, + CommonOption, OutboundHandler, OutboundType, }; #[derive(Default)] @@ -176,11 +176,14 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { - self.fastest(false) + ) -> io::Result { + let d = self + .fastest(false) .await .connect_datagram(sess, resolver) - .await + .await?; + d.append_to_chain(self.name()).await; + Ok(d) } async fn as_map(&self) -> HashMap> { diff --git a/clash_lib/src/proxy/vmess/mod.rs b/clash_lib/src/proxy/vmess/mod.rs index d45a29ea5..4120f6249 100644 --- a/clash_lib/src/proxy/vmess/mod.rs +++ b/clash_lib/src/proxy/vmess/mod.rs @@ -7,7 +7,10 @@ mod vmess_impl; use crate::{ app::{ - dispatcher::{BoxedChainedStream, ChainedStream, ChainedStreamWrapper}, + dispatcher::{ + BoxedChainedDatagram, BoxedChainedStream, ChainedDatagram, ChainedDatagramWrapper, + ChainedStream, ChainedStreamWrapper, + }, dns::ThreadSafeDNSResolver, }, common::errors::{map_io_error, new_io_error}, @@ -20,8 +23,7 @@ use super::{ options::{GrpcOption, Http2Option, HttpOption, WsOption}, transport::{self, Http2Config}, utils::new_tcp_stream, - AnyOutboundDatagram, AnyOutboundHandler, AnyStream, CommonOption, OutboundHandler, - OutboundType, + AnyOutboundHandler, AnyStream, CommonOption, OutboundHandler, OutboundType, }; #[macro_export] @@ -207,7 +209,7 @@ impl OutboundHandler for Handler { &self, sess: &Session, resolver: ThreadSafeDNSResolver, - ) -> io::Result { + ) -> io::Result { let stream = new_tcp_stream( resolver.clone(), self.opts.server.as_str(), @@ -237,13 +239,16 @@ impl OutboundHandler for Handler { let stream = self.inner_proxy_stream(stream, sess, true).await?; - Ok(Box::new(OutboundDatagramVmess::new( + let d = OutboundDatagramVmess::new( stream, SocksAddr::Ip(std::net::SocketAddr::new( IpAddr::V4(remote_addr), sess.destination.port(), )), - )) as AnyOutboundDatagram) - .into() + ); + + let chained = ChainedDatagramWrapper::new(d); + chained.append_to_chain(self.name()).await; + Ok(Box::new(chained)) } } diff --git a/scripts/check_socks5.py b/scripts/check_socks5.py index f419309cc..ca03c8658 100644 --- a/scripts/check_socks5.py +++ b/scripts/check_socks5.py @@ -6,7 +6,7 @@ def check_socks5_tun(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) req = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x05\x62\x61\x69\x64\x75\x03\x63\x6f\x6d\x00\x00\x01\x00\x01" - s.sendto(req, ("198.18.0.2", 53)) + s.sendto(req, ("8.8.8.8", 53)) print(s.getsockname())