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

routing problem for domains with different IP behaviors #4424

Closed
patterniha opened this issue Feb 22, 2025 · 13 comments · Fixed by #4497
Closed

routing problem for domains with different IP behaviors #4424

patterniha opened this issue Feb 22, 2025 · 13 comments · Fixed by #4497

Comments

@patterniha
Copy link
Contributor

patterniha commented Feb 22, 2025

the #4335 issue has become very messy and confusing and many people have misunderstood the problem.
although it was my fault that I couldn't express the problem correctly.

Problem:

assume that built-in-dns return [ip1, ip2] in answer of dns-query for the domain "example.com".
and we want to use ip2 in outbound.

but with the current capabilities of Xray-core this is not possible, even with using features like: loopback, dialerProxy, IPOnDemand, sniffing,...

Application1:

assume that twimg.com return [ip1, ip2]
and ip1 is behind cloudflare and ip2 is behind fastly.
and we have two outbounds: the first is cloudflare-worker(that doesn't support cloudflare ips) and the second is freedom-fragment.

and we want to use worker as much as possible.
so we should choose ip2 and worker-outbound.

Application2:

we have two outbounds: the first is tls-repack-domain-fronting and the second is freedom-fragment: example

cloudflare-ips doesn't support domain-fronting.
but we want to use domain-fronting as much as possible.
so we should choose ip2 and tls-repack outbound.

Suggested solution:

  • in routing rules we save all matched-things(ip/domain) in ctx and then use in outbound, so, even if the address is a domain, we can achieve our goal by using a proper ip-rule and using IPOnDemand/IPIfNonMatch.
Meo597 referenced this issue in Meo597/Xray-core Mar 5, 2025
This commit is a workaround to address requirements similar to XTLS#4335. Due to the nature of the request, the implementation is rather ugly, with IPv4 preference being hardcoded.

The issue in XTLS#4335 is not universal, but my existing functionality happens to be a perfect fit for solving it—only a single line of code needed to be changed.

Changes are based on my feature branch `feature-sniff-override-ip`.
@HeXis-YS
Copy link

HeXis-YS commented Mar 8, 2025

I think there are a lot of solutions out there for your needs.
For example, hosts/DNS with expectIPs+domain/IP-based routing rules.
The key to solving the problem is to limit the IPs returned by DNS query.

@patterniha
Copy link
Contributor Author

I think there are a lot of solutions out there for your needs. For example, hosts/DNS with expectIPs+domain/IP-based routing rules. The key to solving the problem is to limit the IPs returned by DNS query.

No, if returned Ips is only in cloudflare range, i forcibly use another proxy instead of worker/domain-fronting.

I just want to use worker/domain-fronting as much as possible.

Your solution completely disconnects the connection.

@HeXis-YS
Copy link

HeXis-YS commented Mar 8, 2025

I think there are a lot of solutions out there for your needs. For example, hosts/DNS with expectIPs+domain/IP-based routing rules. The key to solving the problem is to limit the IPs returned by DNS query.

No, if returned Ips is only in cloudflare range, i forcibly use another proxy instead of worker/domain-fronting.

I just want to use worker/domain-fronting as much as possible.

Your solution completely disconnects the connection.

Just specify two DNS, one with Fastly IPs as expectIPs and a normal one. If the DNS query result contains both Fastly and Cloudflare IPs, only Fastly ones are retained, and you can route the connections with an IP-based rule. Otherwise, the normal DNS is used as fallback and all IPs are returned.

@patterniha
Copy link
Contributor Author

one with Fastly IPs as expectIPs

So, we have a redundant dns-query for all cloudflare domains!

@HeXis-YS
Copy link

HeXis-YS commented Mar 8, 2025

one with Fastly IPs as expectIPs

So, we have a redundant dns-query for all cloudflare domains!

You can configure to use this DNS to resolve only certain domains. And the results are cached, so there will not be too many duplicate queries.
For example:

      "8.8.8.8",
      {
        "address": "8.8.8.8",
        "domains": ["domain:twimg.com"],
        "expectIPs": ["geoip:fastly"],
        "skipFallback": true
      }

@patterniha
Copy link
Contributor Author

patterniha commented Mar 8, 2025

Certain domains???
We have no information about which domains are behaving this way.
twimg.com is only one domain that i found by chance.

Any domain can behave like this.

@HeXis-YS
Copy link

HeXis-YS commented Mar 8, 2025

Certain domains??? We have no information about which domains are behaving this way. twimg.com is only one domain that i found by chance.

Any domain can behave like this.

Second, with this, we have a redundant query for all cloudflare domains!

Well, in this case, most domains require 2 queries.
Xray-core is not going to be able to fully meet your needs. If this is important to you, I would recommend implementing an external proxy that forwards DNS queries and filters the returned IPs.

@patterniha
Copy link
Contributor Author

patterniha commented Mar 8, 2025

Yes, this feature should be added.
ctx is the key.
Do you read and understand the suggested solution?

(I don't want any of this for myself, I want it for all Iranian users.)

@HeXis-YS
Copy link

HeXis-YS commented Mar 8, 2025

ctx is the key. Do you read and understand the suggested solution?

I think I understand what you are talking about. I don't care about ctx, I just care about solving the problem in the easiest way possible.
In my opinion, limiting the IPs returned by DNS queries is the simplest solution.
For the above solution I proposed, would this solve your problem except that it would send duplicate queries? If this is the case, you can fix the problem of sending duplicate queries by changing just one line of the code.
Change this line

return nil, errExpectedIPNonMatch

to
return ips, nil

@HeXis-YS
Copy link

HeXis-YS commented Mar 8, 2025

I've submitted a similar issue #4146 before, but it doesn't seem to be a priority for developers. And it's hard to consider the current implementation "a bug" since Xray/v2ray has worked this way since a few years ago. No user has reported any practical issue related to this since then.

@patterniha
Copy link
Contributor Author

patterniha commented Mar 8, 2025

geoip:fastly is just an example, other ips could be of any range, so we need "notExpectIPs".

@RPRX @Fangliding

@HeXis-YS solution with some changes completely solve this problem.

Suppose this solution:

{
        "address": "8.8.8.8",
        "expectIPs": ["geoip:!cloudflare"]
},
{
        "address": "8.8.8.8"
{

the problem is that the second dns-query-result may not be the same as the first one.(suppose the first one only contains cloudflare-ips and the second one contains both cloudflare and non-cloudflare ips)
also, another problem is that we have a redundant dns-query for all cloudflare domains(domains that only return cloudflare ips)

so we also need to add "ignoreExpectIPsWhenNoMatch" bool option for each DnsServerObject, and change the:

if len(newIps) == 0 {
return nil, errExpectedIPNonMatch
}

to:

if len(newIps) == 0 {
		if ignoreExpectIPsWhenNoMatch{
                	return ips, nil
                }
		return nil, errExpectedIPNonMatch
	}

///

so with:

{
        "address": "8.8.8.8",
        "expectIPs": ["geoip:!cloudflare"],
        "ignoreExpectIPsWhenNoMatch": true
}

and using "dialerProxy" + "forceIP" in outbound, the problem is completely solved, and we can achieve our goal.

Thank you very much @HeXis-YS.

@RPRX
Copy link
Member

RPRX commented Mar 15, 2025

#4423 (comment)

是否是 expected IP 是另一个问题,这个确实可以加个选项

@patterniha
Copy link
Contributor Author

patterniha commented Mar 15, 2025

@RPRX

I just realized that Xray-core already had "notExpectIPs".

my "notExpectIPs": ["geoip:cloudflare"] feature is exactly the same as "expectIPs": ["geoip:!cloudflare"].

so only "ignoreExpectIPsWhenNoMatch" option should be implemented.

RPRX pushed a commit that referenced this issue Mar 20, 2025
Closes #4424
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants