2021-11-17 08:03:47 +00:00
|
|
|
package gvisor
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-01-08 16:35:45 +00:00
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
|
2021-11-17 08:03:47 +00:00
|
|
|
"net"
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
Common "github.com/Dreamacro/clash/common/net"
|
2021-11-17 08:03:47 +00:00
|
|
|
"github.com/Dreamacro/clash/dns"
|
|
|
|
"github.com/Dreamacro/clash/log"
|
|
|
|
D "github.com/miekg/dns"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/ports"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
|
|
|
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ipv4Zero = tcpip.Address(net.IPv4zero.To4())
|
|
|
|
ipv6Zero = tcpip.Address(net.IPv6zero.To16())
|
|
|
|
)
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
type ListenerWrap struct {
|
|
|
|
net.Listener
|
|
|
|
listener net.Listener
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ListenerWrap) Accept() (conn net.Conn, err error) {
|
|
|
|
conn, err = l.listener.Accept()
|
|
|
|
log.Debugln("[DNS] hijack tcp:%s", l.Addr())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ListenerWrap) Close() error {
|
|
|
|
return l.listener.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *ListenerWrap) Addr() net.Addr {
|
|
|
|
return l.listener.Addr()
|
|
|
|
}
|
|
|
|
|
2021-11-17 08:03:47 +00:00
|
|
|
// DNSServer is DNS Server listening on tun devcice
|
|
|
|
type DNSServer struct {
|
2022-01-08 16:35:45 +00:00
|
|
|
dnsServers []*dns.Server
|
|
|
|
tcpListeners []net.Listener
|
|
|
|
resolver *dns.Resolver
|
|
|
|
stack *stack.Stack
|
|
|
|
udpEndpoints []*dnsEndpoint
|
|
|
|
udpEndpointIDs []*stack.TransportEndpointID
|
2021-11-17 08:03:47 +00:00
|
|
|
tcpip.NICID
|
|
|
|
}
|
|
|
|
|
|
|
|
// dnsEndpoint is a TransportEndpoint that will register to stack
|
|
|
|
type dnsEndpoint struct {
|
|
|
|
stack.TransportEndpoint
|
|
|
|
stack *stack.Stack
|
|
|
|
uniqueID uint64
|
|
|
|
server *dns.Server
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep track of the source of DNS request
|
|
|
|
type dnsResponseWriter struct {
|
|
|
|
s *stack.Stack
|
|
|
|
pkt *stack.PacketBuffer // The request packet
|
|
|
|
id stack.TransportEndpointID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *dnsEndpoint) UniqueID() uint64 {
|
|
|
|
return e.uniqueID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *dnsEndpoint) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) {
|
|
|
|
hdr := header.UDP(pkt.TransportHeader().View())
|
|
|
|
if int(hdr.Length()) > pkt.Data().Size()+header.UDPMinimumSize {
|
|
|
|
// Malformed packet.
|
|
|
|
e.stack.Stats().UDP.MalformedPacketsReceived.Increment()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// server DNS
|
|
|
|
var msg D.Msg
|
|
|
|
msg.Unpack(pkt.Data().AsRange().ToOwnedView())
|
|
|
|
writer := dnsResponseWriter{s: e.stack, pkt: pkt, id: id}
|
2022-01-08 16:35:45 +00:00
|
|
|
log.Debugln("[DNS] hijack udp:%s:%d", id.LocalAddress.String(), id.LocalPort)
|
2021-11-17 08:03:47 +00:00
|
|
|
go e.server.ServeDNS(&writer, &msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *dnsEndpoint) Close() {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *dnsEndpoint) Wait() {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *dnsEndpoint) HandleError(transErr stack.TransportError, pkt *stack.PacketBuffer) {
|
|
|
|
log.Warnln("DNS endpoint get a transport error: %v", transErr)
|
|
|
|
log.Debugln("DNS endpoint transport error packet : %v", pkt)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Abort implements stack.TransportEndpoint.Abort.
|
|
|
|
func (e *dnsEndpoint) Abort() {
|
|
|
|
e.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) LocalAddr() net.Addr {
|
|
|
|
return &net.UDPAddr{IP: net.IP(w.id.LocalAddress), Port: int(w.id.LocalPort)}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) RemoteAddr() net.Addr {
|
|
|
|
return &net.UDPAddr{IP: net.IP(w.id.RemoteAddress), Port: int(w.id.RemotePort)}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) WriteMsg(msg *D.Msg) error {
|
|
|
|
b, err := msg.Pack()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
_, err = w.Write(b)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) TsigStatus() error {
|
|
|
|
// Unsupported
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) TsigTimersOnly(bool) {
|
|
|
|
// Unsupported
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) Hijack() {
|
|
|
|
// Unsupported
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) Write(b []byte) (int, error) {
|
|
|
|
v := buffer.NewView(len(b))
|
|
|
|
copy(v, b)
|
|
|
|
data := v.ToVectorisedView()
|
|
|
|
// w.id.LocalAddress is the source ip of DNS response
|
|
|
|
r, _ := w.s.FindRoute(w.pkt.NICID, w.id.LocalAddress, w.id.RemoteAddress, w.pkt.NetworkProtocolNumber, false /* multicastLoop */)
|
|
|
|
return writeUDP(r, data, w.id.LocalPort, w.id.RemotePort)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *dnsResponseWriter) Close() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// CreateDNSServer create a dns server on given netstack
|
2022-01-08 16:35:45 +00:00
|
|
|
func CreateDNSServer(s *stack.Stack, resolver *dns.Resolver, mapper *dns.ResolverEnhancer, dnsHijack []net.Addr, nicID tcpip.NICID) (*DNSServer, error) {
|
2021-11-17 08:03:47 +00:00
|
|
|
var err error
|
|
|
|
handler := dns.NewHandler(resolver, mapper)
|
|
|
|
serverIn := &dns.Server{}
|
|
|
|
serverIn.SetHandler(handler)
|
2022-01-08 16:35:45 +00:00
|
|
|
tcpDnsArr := make([]net.TCPAddr, 0, len(dnsHijack))
|
|
|
|
udpDnsArr := make([]net.UDPAddr, 0, len(dnsHijack))
|
|
|
|
for _, d := range dnsHijack {
|
|
|
|
switch d.(type) {
|
|
|
|
case *net.TCPAddr:
|
|
|
|
{
|
|
|
|
tcpDnsArr = append(tcpDnsArr, *d.(*net.TCPAddr))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
case *net.UDPAddr:
|
|
|
|
{
|
|
|
|
udpDnsArr = append(udpDnsArr, *d.(*net.UDPAddr))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
endpoints, ids := hijackUdpDns(udpDnsArr, s, serverIn)
|
|
|
|
tcpListeners, dnsServers := hijackTcpDns(tcpDnsArr, s, serverIn)
|
|
|
|
server := &DNSServer{
|
|
|
|
resolver: resolver,
|
|
|
|
stack: s,
|
|
|
|
udpEndpoints: endpoints,
|
|
|
|
udpEndpointIDs: ids,
|
|
|
|
NICID: nicID,
|
|
|
|
tcpListeners: tcpListeners,
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
server.dnsServers = dnsServers
|
2021-11-17 08:03:47 +00:00
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
return server, err
|
|
|
|
}
|
2021-11-17 08:03:47 +00:00
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
func hijackUdpDns(dnsArr []net.UDPAddr, s *stack.Stack, serverIn *dns.Server) ([]*dnsEndpoint, []*stack.TransportEndpointID) {
|
|
|
|
endpoints := make([]*dnsEndpoint, len(dnsArr))
|
|
|
|
ids := make([]*stack.TransportEndpointID, len(dnsArr))
|
|
|
|
for i, dns := range dnsArr {
|
|
|
|
port := dns.Port
|
|
|
|
ip := dns.IP
|
|
|
|
address := tcpip.FullAddress{NIC: nicID, Port: uint16(port)}
|
|
|
|
var protocol tcpip.NetworkProtocolNumber
|
|
|
|
if ip.To4() != nil {
|
|
|
|
address.Addr = tcpip.Address(ip.To4())
|
|
|
|
protocol = ipv4.ProtocolNumber
|
|
|
|
|
|
|
|
} else {
|
|
|
|
address.Addr = tcpip.Address(ip.To16())
|
|
|
|
protocol = ipv6.ProtocolNumber
|
|
|
|
}
|
|
|
|
|
|
|
|
protocolAddr := tcpip.ProtocolAddress{
|
|
|
|
Protocol: protocol,
|
|
|
|
AddressWithPrefix: address.Addr.WithPrefix(),
|
|
|
|
}
|
|
|
|
|
|
|
|
// netstack will only reassemble IP fragments when its' dest ip address is registered in NIC.endpoints
|
|
|
|
if err := s.AddProtocolAddress(nicID, protocolAddr, stack.AddressProperties{}); err != nil {
|
|
|
|
log.Errorln("AddProtocolAddress(%d, %+v, {}): %s", nicID, protocolAddr, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if address.Addr == ipv4Zero || address.Addr == ipv6Zero {
|
|
|
|
address.Addr = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// UDP DNS
|
|
|
|
id := &stack.TransportEndpointID{
|
|
|
|
LocalAddress: address.Addr,
|
|
|
|
LocalPort: uint16(port),
|
|
|
|
RemotePort: 0,
|
|
|
|
RemoteAddress: "",
|
|
|
|
}
|
|
|
|
|
|
|
|
// TransportEndpoint for DNS
|
|
|
|
endpoint := &dnsEndpoint{
|
|
|
|
stack: s,
|
|
|
|
uniqueID: s.UniqueID(),
|
|
|
|
server: serverIn,
|
|
|
|
}
|
|
|
|
|
|
|
|
if tcpiperr := s.RegisterTransportEndpoint(
|
|
|
|
[]tcpip.NetworkProtocolNumber{
|
|
|
|
ipv4.ProtocolNumber,
|
|
|
|
ipv6.ProtocolNumber,
|
|
|
|
},
|
|
|
|
udp.ProtocolNumber,
|
|
|
|
*id,
|
|
|
|
endpoint,
|
|
|
|
ports.Flags{LoadBalanced: true}, // it's actually the SO_REUSEPORT. Not sure it take effect.
|
|
|
|
nicID); tcpiperr != nil {
|
|
|
|
log.Errorln("Unable to start UDP DNS on tun: %v", tcpiperr.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
ids[i] = id
|
|
|
|
endpoints[i] = endpoint
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
return endpoints, ids
|
|
|
|
}
|
2021-11-17 08:03:47 +00:00
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
func hijackTcpDns(dnsArr []net.TCPAddr, s *stack.Stack, serverIn *dns.Server) ([]net.Listener, []*dns.Server) {
|
|
|
|
tcpListeners := make([]net.Listener, len(dnsArr))
|
|
|
|
dnsServers := make([]*dns.Server, len(dnsArr))
|
|
|
|
|
|
|
|
for i, dnsAddr := range dnsArr {
|
|
|
|
var tcpListener net.Listener
|
|
|
|
var v4 bool
|
|
|
|
var err error
|
|
|
|
port := dnsAddr.Port
|
|
|
|
ip := dnsAddr.IP
|
|
|
|
address := tcpip.FullAddress{NIC: nicID, Port: uint16(port)}
|
|
|
|
if ip.To4() != nil {
|
|
|
|
address.Addr = tcpip.Address(ip.To4())
|
|
|
|
v4 = true
|
|
|
|
} else {
|
|
|
|
address.Addr = tcpip.Address(ip.To16())
|
|
|
|
v4 = false
|
|
|
|
}
|
|
|
|
|
|
|
|
if v4 {
|
|
|
|
tcpListener, err = gonet.ListenTCP(s, address, ipv4.ProtocolNumber)
|
|
|
|
} else {
|
|
|
|
tcpListener, err = gonet.ListenTCP(s, address, ipv6.ProtocolNumber)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Errorln("can not listen on tun: %v, hijack tcp[%s] failed", err, dnsAddr)
|
|
|
|
} else {
|
|
|
|
tcpListeners[i] = tcpListener
|
|
|
|
server := &D.Server{Listener: &ListenerWrap{
|
|
|
|
listener: tcpListener,
|
|
|
|
}, Handler: serverIn}
|
|
|
|
dnsServer := dns.Server{}
|
|
|
|
dnsServer.Server = server
|
|
|
|
go dnsServer.ActivateAndServe()
|
|
|
|
dnsServers[i] = &dnsServer
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//
|
|
|
|
//for _, listener := range tcpListeners {
|
|
|
|
// server := &D.Server{Listener: listener, Handler: serverIn}
|
|
|
|
//
|
|
|
|
// dnsServers = append(dnsServers, &dnsServer)
|
|
|
|
// go dnsServer.ActivateAndServe()
|
|
|
|
//}
|
|
|
|
|
|
|
|
return tcpListeners, dnsServers
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Stop stop the DNS Server on tun
|
|
|
|
func (s *DNSServer) Stop() {
|
2022-01-08 16:35:45 +00:00
|
|
|
if s == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(s.udpEndpointIDs); i++ {
|
|
|
|
ep := s.udpEndpoints[i]
|
|
|
|
id := s.udpEndpointIDs[i]
|
|
|
|
// remove udp endpoint from stack
|
|
|
|
s.stack.UnregisterTransportEndpoint(
|
|
|
|
[]tcpip.NetworkProtocolNumber{
|
|
|
|
ipv4.ProtocolNumber,
|
|
|
|
ipv6.ProtocolNumber,
|
|
|
|
},
|
|
|
|
udp.ProtocolNumber,
|
|
|
|
*id,
|
|
|
|
ep,
|
|
|
|
ports.Flags{LoadBalanced: true}, // should match the RegisterTransportEndpoint
|
|
|
|
s.NICID)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, server := range s.dnsServers {
|
|
|
|
server.Shutdown()
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, listener := range s.tcpListeners {
|
|
|
|
listener.Close()
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-04 16:33:42 +00:00
|
|
|
// DnsHijack return the listening address of DNS Server
|
|
|
|
func (t *gvisorAdapter) DnsHijack() []string {
|
2022-01-08 16:35:45 +00:00
|
|
|
dnsHijackArr := make([]string, len(t.dnsServer.udpEndpoints))
|
|
|
|
for _, id := range t.dnsServer.udpEndpointIDs {
|
|
|
|
dnsHijackArr = append(dnsHijackArr, fmt.Sprintf("%s:%d", id.LocalAddress.String(), id.LocalPort))
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
return dnsHijackArr
|
2022-01-04 16:33:42 +00:00
|
|
|
}
|
2021-11-17 08:03:47 +00:00
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
func (t *gvisorAdapter) StopDNSServer() {
|
|
|
|
t.dnsServer.Stop()
|
2022-01-04 16:33:42 +00:00
|
|
|
log.Debugln("tun DNS server stoped")
|
2022-01-08 16:35:45 +00:00
|
|
|
t.dnsServer = nil
|
2022-01-04 16:33:42 +00:00
|
|
|
}
|
2021-11-17 08:03:47 +00:00
|
|
|
|
2022-01-04 16:33:42 +00:00
|
|
|
// ReCreateDNSServer recreate the DNS Server on tun
|
2022-01-08 16:35:45 +00:00
|
|
|
func (t *gvisorAdapter) ReCreateDNSServer(resolver *dns.Resolver, mapper *dns.ResolverEnhancer, dnsHijackArr []string) error {
|
|
|
|
t.StopDNSServer()
|
2021-11-17 08:03:47 +00:00
|
|
|
|
|
|
|
if resolver == nil {
|
|
|
|
return fmt.Errorf("failed to create DNS server on tun: resolver not provided")
|
|
|
|
}
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
if len(dnsHijackArr) == 0 {
|
2022-01-04 16:33:42 +00:00
|
|
|
return fmt.Errorf("failed to create DNS server on tun: len(addrs) == 0")
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
2022-01-08 16:35:45 +00:00
|
|
|
var err error
|
|
|
|
var addrs []net.Addr
|
|
|
|
for _, addr := range dnsHijackArr {
|
|
|
|
var (
|
|
|
|
addrType string
|
|
|
|
hostPort string
|
|
|
|
)
|
|
|
|
|
|
|
|
addrType, hostPort, err = Common.SplitNetworkType(addr)
|
2022-01-04 16:33:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
var (
|
|
|
|
host, port string
|
|
|
|
hasPort bool
|
|
|
|
)
|
|
|
|
|
|
|
|
host, port, hasPort, err = Common.SplitHostPort(hostPort)
|
|
|
|
if !hasPort {
|
|
|
|
port = "53"
|
|
|
|
}
|
|
|
|
|
|
|
|
switch addrType {
|
|
|
|
case "udp", "":
|
|
|
|
{
|
|
|
|
var udpDNS *net.UDPAddr
|
|
|
|
udpDNS, err = net.ResolveUDPAddr("udp", net.JoinHostPort(host, port))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
addrs = append(addrs, udpDNS)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
case "tcp":
|
|
|
|
{
|
|
|
|
var tcpDNS *net.TCPAddr
|
|
|
|
tcpDNS, err = net.ResolveTCPAddr("tcp", net.JoinHostPort(host, port))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
addrs = append(addrs, tcpDNS)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
err = fmt.Errorf("unspported dns scheme:%s", addrType)
|
2022-01-04 16:33:42 +00:00
|
|
|
}
|
2022-01-08 16:35:45 +00:00
|
|
|
|
2021-11-17 08:03:47 +00:00
|
|
|
}
|
2022-01-04 16:33:42 +00:00
|
|
|
|
2022-01-08 16:35:45 +00:00
|
|
|
server, err := CreateDNSServer(t.ipstack, resolver, mapper, addrs, nicID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
t.dnsServer = server
|
|
|
|
|
2021-11-17 08:03:47 +00:00
|
|
|
return nil
|
|
|
|
}
|