Watfaq / clash-rs

custom protocol network proxy
https://watfaq.gitbook.io/clashrs-user-manual/
Apache License 2.0
667 stars 52 forks source link

hickory doesn't support device binding and add fwmark #429

Closed VendettaReborn closed 1 week ago

VendettaReborn commented 3 months ago

we currently use hickory as the dns clients, but there is a potential issue: when using tproxy or tun to handle all the traffics, we cannot apply a fwmark or bind to a network interface, since hickory doesn't offer this option. So, the outbound dns request sent by clash-rs will be intercepted by tproxy/tun. this will cause two PROBLEMS:

  1. when using tproxy with fwmark, it will cause needless interception of packet, since it the dns traffic sent by clash-rs could be directly sent out, but now it's intercepted and go back to clash, and will be relayed, which costs.
  2. when using tun with routing table & dns-hijack is enabled, if we can't recognize the dns traffic sent by clash-rs and other applications, it will cause a endless loop, since all the udp dns requests will be caught by dns hijacker.

In my view, there are two ways to solve it:

  1. make feature requests to hickory, push them to make some changes and add device binding and fwmark to the dns stream's options;
  2. impl our own DnsTcpStream & UdpClientStream, and apply the fwmark and bind_to_device action to the udp/tcp socket.
VendettaReborn commented 3 months ago

@ibigbug thoughts?

VendettaReborn commented 3 months ago

and clash.meta implements dns client by themselves, so to them, this issue doesn't exist

ibigbug commented 3 months ago

good point.

had a quick look, we could probably impl this Trait https://docs.rs/hickory-proto/0.24.1/hickory_proto/xfer/trait.DnsRequestSender.html for UDP and https://docs.rs/hickory-proto/0.24.1/hickory_proto/tcp/trait.Connect.html for TCP, and do something similar to https://docs.rs/hickory-proto/0.24.1/hickory_proto/tcp/struct.TcpClientStream.html#method.with_bind_addr_and_timeout ?

ibigbug commented 3 months ago

it's also good idea to patch upstream, i think there are also potential improvements can be done such as https://github.com/hickory-dns/hickory-dns/issues/2070

ibigbug commented 3 months ago

clash.meta is also intercepting the connection establishment and use that with "github.com/miekg/dns"

ibigbug commented 3 months ago

this looks like a simple AsyncRead/Write https://docs.rs/hickory-proto/0.24.1/hickory_proto/tcp/trait.DnsTcpStream.html we might hook into this with our own new_tcp_socket helper too

VendettaReborn commented 3 months ago

oh, sorry for not noticing the this issue in hickory-dns. Yeah, we can impl it by ourselves, it's a easy job.

VendettaReborn commented 3 months ago

clash.meta is also intercepting the connection establishment and use that with "github.com/miekg/dns"

doesn't clash.meta uses "github.com/miekg/dns" only for the types, like dns.Msg? It seems that all the connections used for dns were established via dialHandler = getDialHandler(...) & dialHandler(...)

ibigbug commented 3 months ago

we somehow do the same in a certain level too https://github.com/Watfaq/clash-rs/blob/446fd937bf1e65e66c3fa8c43b9d697bf57f47ca/clash_lib/src/app/dns/resolver.rs#L196

we do manual message exchange for caching and anti spoofing purposes and use that client to send message to the remote server