Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DomainStrategy Setting Has no Effect in Freedom Outbound while Using jsonv5 Format #2448

Closed
YVjXuB opened this issue Apr 2, 2023 · 11 comments · Fixed by #2550 or #2553
Closed

DomainStrategy Setting Has no Effect in Freedom Outbound while Using jsonv5 Format #2448

YVjXuB opened this issue Apr 2, 2023 · 11 comments · Fixed by #2550 or #2553
Labels
enhancement New feature or request

Comments

@YVjXuB
Copy link

YVjXuB commented Apr 2, 2023

What version of V2Ray are you using?

Tested both 5.4.1 and 5.3.0

What's your scenario of using V2Ray?

On the server side, process v2ray uses custom dns setting from config.json to resolve domain name instead of operate system setting in /etc/resolv.conf

What problems have you encountered?

version 5.3.0

On version 5.3.0, when I tried to add "domainStrategy":"UseIP" in freedom settings, like

{
  "protocol": "freedom",
  "settings": {
    "domainStrategy": "UseIP"
  }
}

it failed to start and here's the output

V2Ray 5.3.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.20 linux/amd64)
A unified platform for anti-censorship.
Failed to start: main/commands: failed to load config: [config.json] > infra/conf/v5cfg: unable to build config > infra/conf/v5cfg: unable to load outbound protocol config > common/registry: unable to parse json content > unknown field "domainStrategy" in v2ray.core.proxy.freedom.SimplifiedConfig

Then I tried to insepct the source code, and figured that DomainStrategy is not in proxy/freedom/config.proto, line 29, message SimplifiedConfig{} while it is shown in line 23,message Config{}.

And also DomainStrategy is not in proxy/freedom/config.pb.go, line 191, type SimplifiedConfig struct{} while it is shown in line 123, type Config struct{}.

I wonder if some changes are needed in those files.

version 5.4.1

After that, I tried to switch to version 5.4.1 because I found pull request #2334 , in which added DomainStrategy for all outbound.

Based on the useage in pull request #2334, I changed the outbound setting like

{
  "protocol": "freedom",
  "domainStrategy": "UseIP",
  "settings": {}
}

And the v2ray started successfully this time. When I created connection through v2ray by curl, the resloving packages captured by tcpdump were sending to 1.1.1.1 which is the setting in /etc/resolv.conf, while they were supposed to send to 8.8.8.8 which is the setting in config.json. Here's the log

V2Ray 5.4.1 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.20.2 linux/amd64)
A unified platform for anti-censorship.
2023/03/31 12:23:28 [Info] app/dns: DNS: created UDP client initialized for 8.8.8.8:53
2023/03/31 12:23:28 [Info] transport/internet/tcp: listening TCP on 127.0.0.1:8080
2023/03/31 12:23:28 [Warning] V2Ray 5.4.1 started
2023/03/31 12:23:38 [Info] [2258904320] proxy/http: request to Method [CONNECT] Host [github.com:443] with URL [//github.com:443]
2023/03/31 12:23:38 [Warning] [2258904320] app/dispatcher: default route for tcp:github.com:443
2023/03/31 12:23:38 [Info] [2258904320] proxy/freedom: opening connection to tcp:github.com:443
2023/03/31 12:23:38 [Info] [2258904320] transport/internet/tcp: dialing TCP to tcp:github.com:443

Since I am not good at golang, I can't figure out why domainStrategy next to protocol has no effect.

Then I changed the outbound setting like

{
  "protocol": "freedom",
  "settings": {
    "domainStrategy": "UseIP"
  }
}

And it failed to start just like version 5.3.0

V2Ray 5.4.1 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.20.2 linux/amd64)
A unified platform for anti-censorship.
Failed to start: main/commands: failed to load config: [config.json] > infra/conf/v5cfg: unable to build config > infra/conf/v5cfg: unable to load outbound protocol config > common/registry: unable to parse json content > unknown field "domainStrategy" in v2ray.core.proxy.freedom.SimplifiedConfig

The problem seems to be the same as version 5.3.0 this time.

Currently, I changed the function useIP() in source file proxy/freedom/config.go to force the UseIP strategy and rebuild the v2ray.

func (c *Config) useIP() bool {
	return true
}

It might cause some bug, but it's fine so far.

What's your expectation?

With format jsonv5, the process will use internal dns settings to resolve domain name when outbound setting is either

{
  "protocol": "freedom",
  "domainStrategy": "UseIP",
  "settings": {}
}

or

{
  "protocol": "freedom",
  "settings": {
    "domainStrategy": "UseIP"
  }
}

I don't use v4 json format because 'bindToDevice' is not supported in it.

Please attach your configuration here

Server configuration:

Process failed to start with this configuration:

{
  "dns": {
    "nameServer": [{
      "address": {
        "address": "8.8.8.8",
        "port": 53
      }
    }]
  },
  "inbounds": [
    {
      "port": 8080,
      "protocol": "http",
      "listen": "127.0.0.1"
    }
  ],
    "outbounds": [
    {
      "protocol": "freedom",
      //"domainStrategy": "UseIP",
      "settings": {
        "domainStrategy": "UseIP"
      }
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ],
  "router": {
    "domainStrategy": "AsIs"
  },
  "log": {
    "error": {
      "type": "Console",
      "level": "Info"
    }
  }
}

"domainStrategy": "UseIP" has no effect with this configuration

{
  "dns": {
    "nameServer": [{
      "address": {
        "address": "8.8.8.8",
        "port": 53
      }
    }]
  },
  "inbounds": [
    {
      "port": 8080,
      "protocol": "http",
      "listen": "127.0.0.1"
    }
  ],
    "outbounds": [
    {
      "protocol": "freedom",
      "domainStrategy": "UseIP",
      "settings": {
        //"domainStrategy": "UseIP"
      }
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ],
  "router": {
    "domainStrategy": "AsIs"
  },
  "log": {
    "error": {
      "type": "Console",
      "level": "Info"
    }
  }
}

Client configuration:

Using command curl

https_proxy=http://127.0.0.1:1080 curl https://github.com
@AkinoKaede AkinoKaede added the enhancement New feature or request label Apr 7, 2023
@bayard
Copy link

bayard commented May 12, 2023

While I am using v5.4.1 and had tried every methods to resolve IP for every requests before sending them to outbound (that's the purpose what "domainStrategy": "UseIP" phrase designed for), none of them works. I also tested same configuration under xray environment with success. That's should be some bugs cause the issue and needed to be fixed, to bring this key feature works again.

@bayard
Copy link

bayard commented May 12, 2023

While I am using v5.4.1 and had tried every methods to resolve IP for every requests before sending them to outbound (that's the purpose what "domainStrategy": "UseIP" phrase designed for), none of them works. I also tested same configuration under xray environment with success. That's should be some bugs cause the issue and needed to be fixed, to bring this key feature works again.

After switch back to v5.2.1, the UseIP stragegy worked normally, which resolve IP for routed request first, then initiate new request using resolved IP to the outbound chain.

@Vigilans
Copy link
Contributor

Vigilans commented May 29, 2023

@YVjXuB

Based on the useage in pull request #2334, I changed the outbound setting like

{
 "protocol": "freedom",
 "domainStrategy": "UseIP",
 "settings": {}
}

And the v2ray started successfully this time. When I created connection through v2ray by curl, the resloving packages captured by tcpdump were sending to 1.1.1.1 which is the setting in /etc/resolv.conf, while they were supposed to send to 8.8.8.8 which is the setting in config.json.

This is because in #2334 I only added config support for jsonv4, and forgot to add it for jsonv5 (because I am still sticking to jsonv4). Jsonv5 support is missing in:

func (c OutboundConfig) BuildV5(ctx context.Context) (proto.Message, error) {
senderSettings := &proxyman.SenderConfig{}
if c.SendThrough != nil {
address := c.SendThrough
if address.Family().IsDomain() {
return nil, newError("unable to send through: " + address.String())
}
senderSettings.Via = address.Build()
}

I will add a PR to bring it to jsonv5.

Then I tried to insepct the source code, and figured that DomainStrategy is not in proxy/freedom/config.proto, line 29, message SimplifiedConfig{} while it is shown in line 23,message Config{}.

And also DomainStrategy is not in proxy/freedom/config.pb.go, line 191, type SimplifiedConfig struct{} while it is shown in line 123, type Config struct{}.

I wonder if some changes are needed in those files.

Yes, it is missing and I also wonder the reason. Since we have domainStrategy for all outbounds now, should we only use the global one or add to freedom outbound settings again for compatibility? @AkinoKaede

@Vigilans
Copy link
Contributor

@bayard

While I am using v5.4.1 and had tried every methods to resolve IP for every requests before sending them to outbound (that's the purpose what "domainStrategy": "UseIP" phrase designed for), none of them works. I also tested same configuration under xray environment with success. That's should be some bugs cause the issue and needed to be fixed, to bring this key feature works again.

Are you using jsonv4 or jsonv5? For jsonv4 I've just tested that both way mentioned in this issue will work. Could you share you config here?

@bayard
Copy link

bayard commented May 29, 2023

@bayard

While I am using v5.4.1 and had tried every methods to resolve IP for every requests before sending them to outbound (that's the purpose what "domainStrategy": "UseIP" phrase designed for), none of them works. I also tested same configuration under xray environment with success. That's should be some bugs cause the issue and needed to be fixed, to bring this key feature works again.

Are you using jsonv4 or jsonv5? For jsonv4 I've just tested that both way mentioned in this issue will work. Could you share you config here?

Thanks for your reply.

Because I had switch to xray and the config file might had been modified to compatible to xray's syntax, the following config may not be exact the same with mentioned one in my previous reply:

`{
// Cloudflare的proxy模式中,40000端口的socks无法通过udp dns查询,导致dns解析失败。劫持基于IP地址的DoH dns请求,通过代理直接解析
"log": {
"loglevel": "debug"
},
"dns": {
"servers": [
"https://1.1.1.1/dns-query",
"https://1.0.0.1/dns-query"

    ]
},
"outbounds": [
    {
        "tag": "dns-out",
        "protocol": "dns"
    },
    {
        "tag": "proxy-dispatcher",
        "mux": {
            "enabled": true,
            "concurrency": -1,
            "xudpConcurrency": 256,
            "xudpProxyUDP443": "allow"
        },
        "protocol": "freedom",
        "settings": {
            "domainStrategy": "UseIP"
        },
        "proxySettings": {
            "tag": "proxy"
        }
    },
    {
        "tag": "overseasdns-dispatcher",
        "protocol": "freedom",
        "proxySettings": {
            "tag": "proxy",
            "transportLayer": true
        },
        "mux": {
            "enabled": true,
            "concurrency": -1,
            "xudpConcurrency": 256,
            "xudpProxyUDP443": "allow"
        }
    },
    {
        "protocol": "socks",
        "settings": {
            "servers": [
                {
                    "address": "127.0.0.1",
                    "port": 40000
                }
            ]
        },
        "tag": "proxy"
    },
    {
        "tag": "direct",
        "protocol": "freedom",
        "settings": {}
    }
],
"inbounds": [
    {
        "tag": "socks-in",
        "listen": "127.0.0.1",
        "port": 2162,
        "protocol": "socks",
        "settings": {
            "udp": true
        },
        "sniffing": {
            "enabled": true,
            "destOverride": [
                "http",
                "tls"
            ]
        }
    },
    {
        "tag": "http-in",
        "listen": "127.0.0.1",
        "port": 2161,
        "protocol": "http",
        "sniffing": {
            "enabled": true,
            "destOverride": [
                "http",
                "tls"
            ]
        },
        "settings": {
            "auth": "noauth",
            "udp": false
        }
    }
],
"routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
        {
            "type": "field",
            "inboundTag": [
                "socks-in",
                "http-in"
            ],
            "port": 53,
            "outboundTag": "dns-out"
        },
        {
            "type": "field",
            "ip": [
                "1.1.1.1",
                "1.0.0.1"
            ],
            "outboundTag": "overseasdns-dispatcher"
        },
        {
            "type": "field",
            "outboundTag": "Reject",
            "domain": [
                "geosite:category-ads-all"
            ]
        },
        {
            "type": "field",
            "outboundTag": "direct",
            "domain": [
                "geosite:private",
                "geosite:cn"
            ]
        },
        {
            "type": "field",
            "outboundTag": "direct",
            "ip": [
                "geoip:cn",
                "geoip:private"
            ]
        },
        {
            "type": "field",
            "inboundTag": [
                "socks-in",
                "http-in"
            ],
            "outboundTag": "proxy-dispatcher"
        }
    ]
}

}`

@Vigilans
Copy link
Contributor

Vigilans commented May 29, 2023

@bayard I've discovered the root cause of your issue. It is indeed a regression bug introduced after #2334.

There are two reasons for your failure:

  1. After [app/proxyman] DomainStrategy support for all outbounds #2334, using domainStrategy with proxySettings, the original outbound's domainStrategy will not be honored. This is because domain resolving is postponed to the very end before dialing, and proxySettings happened before it, and the domainStrategy information is lost.

  2. Even if we pass the domainStrategy information from freedom outbound to socks5 outbound, or just specify domainStrategy for socks5 outbound, the domain will still not be resolved, as socks5 outbound will only try to dial its proxy address (127.0.0.1 in this case), so domainStrategy for such outbound (socks5, vmess, etc) are for specifying the strategy for resolving their remote server addresses.

I'll figure out a way to resolve this issue.

Btw, are your using freedom and proxySettings to socks5 is for resolving the proxied domain in client side instead of socks5 server side?

@Vigilans
Copy link
Contributor

Vigilans commented May 29, 2023

Btw, are your using freedom and proxySettings to socks5 is for resolving the proxied domain in client side instead of socks5 server side?

This also raises a question not discussed in #2334: By using domainStrategy for outbounds like socks5 and vmess, what domain should be resolved? :

  1. The proxy server's address (will be used for dialing)
  2. The connection destination (written in request header and sent to proxy server)

Should it be 1 (current behavior), or 2 (so it behaves like freedom outbound, maybe what @bayard's freedom + proxySettings is for), or both?

@AkinoKaede @xiaokangwang

@bayard
Copy link

bayard commented May 30, 2023

@bayard I've discovered the root cause of your issue. It is indeed a regression bug introduced after #2334.

There are two reasons for your failure:

  1. After [app/proxyman] DomainStrategy support for all outbounds #2334, using domainStrategy with proxySettings, the original outbound's domainStrategy will not be honored. This is because domain resolving is postponed to the very end before dialing, and proxySettings happened before it, and the domainStrategy information is lost.
  2. Even if we pass the domainStrategy information from freedom outbound to socks5 outbound, or just specify domainStrategy for socks5 outbound, the domain will still not be resolved, as socks5 outbound will only try to dial its proxy address (127.0.0.1 in this case), so domainStrategy for such outbound (socks5, vmess, etc) are for specifying the strategy for resolving their remote server addresses.

I'll figure out a way to resolve this issue.

From the traced log output, the v2ray's behavior was like what you explained:

What I expected was the DNS requests(hijacked by dns-out) should be routed to DNS servers specified in DNS directive, then dial outbound proxy using resolved IP instead of domain name because the socks proxy unable to handle DNS resolution correctly (passing requests with domain name to cloudflare WARP's socks proxy will failed, the reason might related to socks version compatibility or internal DNS address blocked by GFW).

But the log revealed that hijacked DNS routed and IP resolved correctly, and parallelly a request using original domain name also dialed to outbound socks proxy and failed because the proxy unable to handle requests using domain name. It seemed that UseIP domainStrategy with proxySettings had no effect in this circumstance.

Btw, are your using freedom and proxySettings to socks5 is for resolving the proxied domain in client side instead of socks5 server side?

YES. The outbound socks5 was cloudflare WARP, it seems that the proxy only support socks4 or internal DNS resolution blocked/poisoned by GFW, so I tried to resolve IP in client side.

@Vigilans
Copy link
Contributor

YES. The outbound socks5 was cloudflare WARP, it seems that the proxy only support socks4 or internal DNS resolution blocked/poisoned by GFW, so I tried to resolve IP in client side.

So this proves that for domainStrategy for socks and vmess outbound, we need option 3: both proxy server's address and target destination will be resolved.

@57a4c324e742
Copy link
Contributor

Shouldn't it be flagged as a bug instead of an enhancement? The JSONv5 configuration format removed the "domanStrategy" configuration option from the "freedom" outbound. This causes DNS queries to be leaked to unencrypted system DNS.

I will add a PR to bring it to jsonv5.

@Vigilans I've checked the list of pull requests and can't find a pull request to fix this. I made a pull request for you.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 3, 2023

This issue is stale because it has been open 120 days with no activity. Remove stale label or comment or this will be closed in 5 days

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
5 participants