Add fakeip support

This commit is contained in:
世界 2023-03-25 12:03:23 +08:00
parent aa94cfb876
commit 9bca5a517f
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
28 changed files with 689 additions and 62 deletions

View file

@ -24,6 +24,7 @@ import (
"github.com/sagernet/sing-box/ntp"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/outbound"
"github.com/sagernet/sing-box/transport/fakeip"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing-vmess"
@ -66,6 +67,7 @@ type Router struct {
transportMap map[string]dns.Transport
transportDomainStrategy map[dns.Transport]dns.DomainStrategy
dnsReverseMapping *DNSReverseMapping
fakeIPStore adapter.FakeIPStore
interfaceFinder myInterfaceFinder
autoDetectInterface bool
defaultInterface string
@ -178,12 +180,8 @@ func NewRouter(
} else {
continue
}
} else if notIpAddress != nil {
switch serverURL.Scheme {
case "rcode", "dhcp":
default:
return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
}
} else if notIpAddress != nil && strings.Contains(server.Address, ".") {
return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
}
}
transport, err := dns.CreateTransport(tag, ctx, logFactory.NewLogger(F.ToString("dns/transport[", tag, "]")), detour, server.Address)
@ -239,6 +237,18 @@ func NewRouter(
router.dnsReverseMapping = NewDNSReverseMapping()
}
if fakeIPOptions := dnsOptions.FakeIP; fakeIPOptions != nil && dnsOptions.FakeIP.Enabled {
var inet4Range netip.Prefix
var inet6Range netip.Prefix
if fakeIPOptions.Inet4Range != nil {
inet4Range = fakeIPOptions.Inet4Range.Build()
}
if fakeIPOptions.Inet6Range != nil {
inet6Range = fakeIPOptions.Inet6Range.Build()
}
router.fakeIPStore = fakeip.NewStore(router, inet4Range, inet6Range)
}
usePlatformDefaultInterfaceMonitor := platformInterface != nil && platformInterface.UsePlatformDefaultInterfaceMonitor()
needInterfaceMonitor := options.AutoDetectInterface || common.Any(inbounds, func(inbound option.Inbound) bool {
return inbound.HTTPOptions.SetSystemProxy || inbound.MixedOptions.SetSystemProxy || inbound.TunOptions.AutoRoute
@ -452,6 +462,12 @@ func (r *Router) Start() error {
return E.Cause(err, "initialize DNS rule[", i, "]")
}
}
if r.fakeIPStore != nil {
err := r.fakeIPStore.Start()
if err != nil {
return err
}
}
for i, transport := range r.transports {
err := transport.Start()
if err != nil {
@ -517,6 +533,12 @@ func (r *Router) Close() error {
return E.Cause(err, "close time service")
})
}
if r.fakeIPStore != nil {
r.logger.Trace("closing fakeip store")
err = E.Append(err, r.fakeIPStore.Close(), func(err error) error {
return E.Cause(err, "close fakeip store")
})
}
return err
}
@ -533,6 +555,10 @@ func (r *Router) DefaultOutbound(network string) adapter.Outbound {
}
}
func (r *Router) FakeIPStore() adapter.FakeIPStore {
return r.fakeIPStore
}
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
if metadata.InboundDetour != "" {
if metadata.LastInbound == metadata.InboundDetour {
@ -585,6 +611,19 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
metadata.Destination = M.Socksaddr{Addr: netip.IPv4Unspecified()}
return r.RoutePacketConnection(ctx, uot.NewConn(conn, uot.Request{}), metadata)
}
if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr)
if !loaded {
return E.New("missing fakeip context")
}
metadata.Destination = M.Socksaddr{
Fqdn: domain,
Port: metadata.Destination.Port,
}
r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
}
if metadata.InboundOptions.SniffEnabled {
buffer := buf.NewPacket()
buffer.FullReset()
@ -675,6 +714,21 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
return nil
}
metadata.Network = N.NetworkUDP
var originAddress M.Socksaddr
if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) {
domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr)
if !loaded {
return E.New("missing fakeip context")
}
originAddress = metadata.Destination
metadata.Destination = M.Socksaddr{
Fqdn: domain,
Port: metadata.Destination.Port,
}
r.logger.DebugContext(ctx, "found fakeip domain: ", domain)
}
if metadata.InboundOptions.SniffEnabled {
buffer := buf.NewPacket()
buffer.FullReset()
@ -733,6 +787,9 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
}
}
if originAddress.IsValid() {
conn = fakeip.NewNATPacketConn(conn, originAddress, metadata.Destination)
}
return detour.NewPacketConnection(ctx, conn, metadata)
}

View file

@ -57,6 +57,10 @@ func (r *abstractDefaultRule) UpdateGeosite() error {
}
func (r *abstractDefaultRule) Match(metadata *adapter.InboundContext) bool {
if len(r.allItems) == 0 {
return true
}
for _, item := range r.items {
if !item.Match(metadata) {
return r.invert