1
0
mirror of https://github.com/MetaCubeX/mihomo.git synced 2026-10-10 12:13:10 +08:00
Files
2026-09-11 09:41:09 +08:00

99 lines
3.0 KiB
Go

package easytier
import (
"context"
"errors"
"net"
"net/netip"
"testing"
"time"
"github.com/metacubex/mihomo/component/resolver"
"github.com/easytier/easytier/easytier-go/platform"
D "github.com/miekg/dns"
)
type testDNSResolver struct {
resolver.Resolver
exchange func(context.Context, *D.Msg) (*D.Msg, error)
}
func (*testDNSResolver) Invalid() bool { return true }
func (r *testDNSResolver) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) {
return r.exchange(ctx, m)
}
func TestDNSRecordsUseMihomoResolver(t *testing.T) {
oldProxy, oldDefault := resolver.ProxyServerHostResolver, net.DefaultResolver
t.Cleanup(func() {
resolver.ProxyServerHostResolver = oldProxy
net.DefaultResolver = oldDefault
})
net.DefaultResolver = &net.Resolver{
PreferGo: true,
Dial: func(context.Context, string, string) (net.Conn, error) {
t.Error("net.DefaultResolver was used")
return nil, errors.New("forbidden resolver")
},
}
resolver.ProxyServerHostResolver = &testDNSResolver{exchange: func(_ context.Context, m *D.Msg) (*D.Msg, error) {
reply := new(D.Msg).SetReply(m)
switch m.Question[0].Qtype {
case D.TypeTXT:
reply.Answer = []D.RR{&D.TXT{Txt: []string{"ok"}}}
case D.TypeSRV:
reply.Answer = []D.RR{&D.SRV{Target: "peer.example.", Port: 11010}}
}
return reply, nil
}}
txt, err := (DNSResolver{}).LookupTXT(context.Background(), platform.DNSQuery{Host: "example"})
if err != nil || txt != "ok" {
t.Fatalf("TXT: %q %v", txt, err)
}
srv, err := (DNSResolver{}).LookupSRV(context.Background(), platform.DNSQuery{Host: "example"})
if err != nil || len(srv) != 1 || srv[0].Target != "peer.example." || srv[0].Port != 11010 {
t.Fatalf("SRV: %v %v", srv, err)
}
}
func TestUDPBindPreservesWildcardPort(t *testing.T) {
_, address := udpBind(platform.UDPBindOptions{LocalAddr: &net.UDPAddr{Port: 45678}})
_, port, err := net.SplitHostPort(address)
if err != nil || port != "45678" {
t.Fatalf("%s: %v", address, err)
}
}
type forbiddenDialer struct{}
func (forbiddenDialer) DialContext(context.Context, string, string) (net.Conn, error) {
panic("unexpected proxy session")
}
func (forbiddenDialer) ListenPacket(context.Context, string, string, netip.AddrPort) (net.PacketConn, error) {
panic("unexpected proxy socket")
}
func TestListenTCPInternalAllowedThroughProxyDialer(t *testing.T) {
factory := SocketFactory{Dialer: forbiddenDialer{}}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
listener, err := factory.ListenTCP(ctx, platform.TCPListenOptions{
Bind: platform.TCPBindOptions{LocalAddr: &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)}},
Purpose: platform.TCPListenProxyNAT,
})
if err != nil {
t.Fatal(err)
}
defer listener.Close()
if _, err := factory.ListenTCP(ctx, platform.TCPListenOptions{
Bind: platform.TCPBindOptions{LocalAddr: &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1)}},
Purpose: platform.TCPListenDirect,
}); err == nil {
t.Fatal("external listener through proxy must fail")
}
}