| skipped 22 lines |
23 | 23 | | "github.com/sagernet/sing-box/log" |
24 | 24 | | "github.com/sagernet/sing-box/ntp" |
25 | 25 | | "github.com/sagernet/sing-box/option" |
| 26 | + | "github.com/sagernet/sing-box/transport/fakeip" |
26 | 27 | | "github.com/sagernet/sing-dns" |
27 | 28 | | "github.com/sagernet/sing-tun" |
28 | 29 | | "github.com/sagernet/sing-vmess" |
| skipped 58 lines |
87 | 88 | | transportMap map[string]dns.Transport |
88 | 89 | | transportDomainStrategy map[dns.Transport]dns.DomainStrategy |
89 | 90 | | dnsReverseMapping *DNSReverseMapping |
| 91 | + | fakeIPStore adapter.FakeIPStore |
90 | 92 | | interfaceFinder myInterfaceFinder |
91 | 93 | | autoDetectInterface bool |
92 | 94 | | defaultInterface string |
| skipped 124 lines |
217 | 219 | | } else { |
218 | 220 | | continue |
219 | 221 | | } |
220 | | - | } else if notIpAddress != nil { |
221 | | - | switch serverURL.Scheme { |
222 | | - | case "rcode", "dhcp": |
223 | | - | default: |
224 | | - | return nil, E.New("parse dns server[", tag, "]: missing address_resolver") |
225 | | - | } |
| 222 | + | } else if notIpAddress != nil && strings.Contains(server.Address, ".") { |
| 223 | + | return nil, E.New("parse dns server[", tag, "]: missing address_resolver") |
226 | 224 | | } |
227 | 225 | | } |
228 | 226 | | transport, err := dns.CreateTransport(ctx, logFactory.NewLogger(F.ToString("dns/transport[", tag, "]")), detour, server.Address) |
| skipped 49 lines |
278 | 276 | | router.dnsReverseMapping = NewDNSReverseMapping() |
279 | 277 | | } |
280 | 278 | | |
| 279 | + | if fakeIPOptions := dnsOptions.FakeIP; fakeIPOptions != nil && dnsOptions.FakeIP.Enabled { |
| 280 | + | var inet4Range netip.Prefix |
| 281 | + | var inet6Range netip.Prefix |
| 282 | + | if fakeIPOptions.Inet4Range != nil { |
| 283 | + | inet4Range = fakeIPOptions.Inet4Range.Build() |
| 284 | + | } |
| 285 | + | if fakeIPOptions.Inet6Range != nil { |
| 286 | + | inet6Range = fakeIPOptions.Inet6Range.Build() |
| 287 | + | } |
| 288 | + | router.fakeIPStore = fakeip.NewStore(router, inet4Range, inet6Range) |
| 289 | + | } |
| 290 | + | |
281 | 291 | | needInterfaceMonitor := platformInterface == nil && (options.AutoDetectInterface || common.Any(inbounds, func(inbound option.Inbound) bool { |
282 | 292 | | return inbound.HTTPOptions.SetSystemProxy || inbound.MixedOptions.SetSystemProxy || inbound.TunOptions.AutoRoute |
283 | 293 | | })) |
| skipped 200 lines |
484 | 494 | | return E.Cause(err, "initialize DNS rule[", i, "]") |
485 | 495 | | } |
486 | 496 | | } |
| 497 | + | if r.fakeIPStore != nil { |
| 498 | + | err := r.fakeIPStore.Start() |
| 499 | + | if err != nil { |
| 500 | + | return err |
| 501 | + | } |
| 502 | + | } |
487 | 503 | | for i, transport := range r.transports { |
488 | 504 | | err := transport.Start() |
489 | 505 | | if err != nil { |
| skipped 34 lines |
524 | 540 | | r.networkMonitor, |
525 | 541 | | r.packageManager, |
526 | 542 | | r.timeService, |
| 543 | + | r.fakeIPStore, |
527 | 544 | | ) |
528 | 545 | | } |
529 | 546 | | |
| skipped 10 lines |
540 | 557 | | } |
541 | 558 | | } |
542 | 559 | | |
| 560 | + | func (r *Router) FakeIPStore() adapter.FakeIPStore { |
| 561 | + | return r.fakeIPStore |
| 562 | + | } |
| 563 | + | |
543 | 564 | | func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { |
544 | 565 | | if metadata.InboundDetour != "" { |
545 | 566 | | if metadata.LastInbound == metadata.InboundDetour { |
| skipped 46 lines |
592 | 613 | | metadata.Destination = M.Socksaddr{Addr: netip.IPv4Unspecified()} |
593 | 614 | | return r.RoutePacketConnection(ctx, uot.NewConn(conn, uot.Request{}), metadata) |
594 | 615 | | } |
| 616 | + | |
| 617 | + | if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) { |
| 618 | + | domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr) |
| 619 | + | if !loaded { |
| 620 | + | return E.New("missing fakeip context") |
| 621 | + | } |
| 622 | + | metadata.Destination = M.Socksaddr{ |
| 623 | + | Fqdn: domain, |
| 624 | + | Port: metadata.Destination.Port, |
| 625 | + | } |
| 626 | + | r.logger.DebugContext(ctx, "found fakeip domain: ", domain) |
| 627 | + | } |
| 628 | + | |
595 | 629 | | if metadata.InboundOptions.SniffEnabled { |
596 | 630 | | buffer := buf.NewPacket() |
597 | 631 | | buffer.FullReset() |
| skipped 80 lines |
678 | 712 | | return nil |
679 | 713 | | } |
680 | 714 | | metadata.Network = N.NetworkUDP |
| 715 | + | |
| 716 | + | var originAddress M.Socksaddr |
| 717 | + | if r.fakeIPStore != nil && r.fakeIPStore.Contains(metadata.Destination.Addr) { |
| 718 | + | domain, loaded := r.fakeIPStore.Lookup(metadata.Destination.Addr) |
| 719 | + | if !loaded { |
| 720 | + | return E.New("missing fakeip context") |
| 721 | + | } |
| 722 | + | originAddress = metadata.Destination |
| 723 | + | metadata.Destination = M.Socksaddr{ |
| 724 | + | Fqdn: domain, |
| 725 | + | Port: metadata.Destination.Port, |
| 726 | + | } |
| 727 | + | r.logger.DebugContext(ctx, "found fakeip domain: ", domain) |
| 728 | + | } |
| 729 | + | |
681 | 730 | | if metadata.InboundOptions.SniffEnabled { |
682 | 731 | | buffer := buf.NewPacket() |
683 | 732 | | buffer.FullReset() |
| skipped 49 lines |
733 | 782 | | if statsService := r.v2rayServer.StatsService(); statsService != nil { |
734 | 783 | | conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn) |
735 | 784 | | } |
| 785 | + | } |
| 786 | + | if originAddress.IsValid() { |
| 787 | + | conn = fakeip.NewNATPacketConn(conn, originAddress, metadata.Destination) |
736 | 788 | | } |
737 | 789 | | return detour.NewPacketConnection(ctx, conn, metadata) |
738 | 790 | | } |
| skipped 158 lines |