Skip to content

Commit

Permalink
Add fakedns+others sniffing mode
Browse files Browse the repository at this point in the history
"fakedns+others" means if the request IP is in the range of fakes,
when fakeDNS cache missed (most likely due to reboot), "tls" and "http"
sniffer will be used to identify domain
  • Loading branch information
yuhan6665 committed Feb 21, 2021
1 parent efb9632 commit b17dbd5
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 5 deletions.
19 changes: 16 additions & 3 deletions app/dispatcher/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/v2fly/v2ray-core/v4/common/net"
"github.com/v2fly/v2ray-core/v4/common/protocol"
"github.com/v2fly/v2ray-core/v4/common/session"
"github.com/v2fly/v2ray-core/v4/features/dns"
"github.com/v2fly/v2ray-core/v4/features/outbound"
"github.com/v2fly/v2ray-core/v4/features/policy"
"github.com/v2fly/v2ray-core/v4/features/routing"
Expand Down Expand Up @@ -177,7 +178,11 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
return inboundLink, outboundLink
}

func shouldOverride(result SniffResult, domainOverride []string) bool {
func shouldOverride(ctx context.Context, result SniffResult, domainOverride []string, destination net.Destination) bool {
var fakeDNSEngine dns.FakeDNSEngine
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
fakeDNSEngine = fdns
})
protocolString := result.Protocol()
if resComp, ok := result.(SnifferResultComposite); ok {
protocolString = resComp.ProtocolForDomainResult()
Expand All @@ -186,6 +191,14 @@ func shouldOverride(result SniffResult, domainOverride []string) bool {
if strings.HasPrefix(protocolString, p) {
return true
}
if protocolString == "fakedns" && p == "fakedns+others" {
return true
}
if fakeDNSEngine != nil && protocolString != "bittorrent" && p == "fakedns+others" &&
fakeDNSEngine.GetFakeIPRange().Contains(destination.Address.IP()) {
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx))
return true
}
}
return false
}
Expand Down Expand Up @@ -215,7 +228,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
result, err := sniffer(ctx, nil, true)
if err == nil {
content.Protocol = result.Protocol()
if shouldOverride(result, sniffingRequest.OverrideDestinationForProtocol) {
if shouldOverride(ctx, result, sniffingRequest.OverrideDestinationForProtocol, destination) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
destination.Address = net.ParseAddress(domain)
Expand All @@ -233,7 +246,7 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
if err == nil {
content.Protocol = result.Protocol()
}
if err == nil && shouldOverride(result, sniffingRequest.OverrideDestinationForProtocol) {
if err == nil && shouldOverride(ctx, result, sniffingRequest.OverrideDestinationForProtocol, destination) {
domain := result.Domain()
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
destination.Address = net.ParseAddress(domain)
Expand Down
6 changes: 6 additions & 0 deletions app/dns/fakedns/fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,15 @@ func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
if k, ok := fkdns.domainToIP.GetKeyFromValue(ip); ok {
return k.(string)
}
newError("A fake ip request to ", ip, ", however there is no matching domain name in fake DNS").AtInfo().WriteToLog()
return ""
}

// GetFakeIPRange return fake IP range from configuration
func (fkdns *Holder) GetFakeIPRange() *gonet.IPNet {
return fkdns.ipRange
}

func init() {
common.Must(common.RegisterConfig((*FakeDnsPool)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
var f *Holder
Expand Down
2 changes: 1 addition & 1 deletion app/proxyman/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ message SniffingConfig {
bool enabled = 1;

// Override target destination if sniff'ed protocol is in the given list.
// Supported values are "http", "tls", "fakedns".
// Supported values are "http", "tls", "fakedns", "fakedns+others".
repeated string destination_override = 2;

// Whether should only try to sniff metadata without waiting for client input.
Expand Down
3 changes: 3 additions & 0 deletions features/dns/fakedns.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dns

import (
gonet "net"

"github.com/v2fly/v2ray-core/v4/common/net"
"github.com/v2fly/v2ray-core/v4/features"
)
Expand All @@ -9,4 +11,5 @@ type FakeDNSEngine interface {
features.Feature
GetFakeIPForDomain(domain string) []net.Address
GetDomainFromFakeDNS(ip net.Address) string
GetFakeIPRange() *gonet.IPNet
}
2 changes: 1 addition & 1 deletion infra/conf/fakedns.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (FakeDNSPostProcessingStage) Process(conf *Config) error {
for _, v := range inbounds {
if v.SniffingConfig != nil && v.SniffingConfig.Enabled && v.SniffingConfig.DestOverride != nil {
for _, dov := range *v.SniffingConfig.DestOverride {
if dov == "fakedns" {
if dov == "fakedns" || dov == "fakedns+others" {
found = true
}
}
Expand Down
2 changes: 2 additions & 0 deletions infra/conf/v2ray.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
p = append(p, "tls")
case "fakedns":
p = append(p, "fakedns")
case "fakedns+others":
p = append(p, "fakedns+others")
default:
return nil, newError("unknown protocol: ", domainOverride)
}
Expand Down

0 comments on commit b17dbd5

Please sign in to comment.