XTLS / Xray-core

Xray, Penetrates Everything. Also the best v2ray-core, with XTLS support. Fully compatible configuration.
https://t.me/projectXray
Mozilla Public License 2.0
25.62k stars 3.95k forks source link

⚠️ Please help to do this 🙏 - route to Multi outbounds by value of "Host" in request header 🙏 #2321

Closed hosein-moayedi closed 7 months ago

hosein-moayedi commented 1 year ago

Hey guys! I want to do this and I know this should be work but I very tried to do this and failed!

env: 1 Iran server --- ir.mydomain.site, 1 Germany server --- de.mydomain.site, 1 Finlond server --- fl.mydomain.site

desc: I want to give 2 vless configs to the client from the iran server with define one inbound inside of the iran server and all info of these two configs is same, like address, port, type, etc.. and there is just one thing that is differents. that is value of "Host" parameter on request header in WS or TCP that is the domain of my target server that iran server should route all client traffic to that target server.

ex: if the user selected config 1 with address: "ir.mydomain.site" and "Host"="fl.mydomain.site", he should connect to Iran server and rout to Finlond server through outbound of Finland that I defined in iran outbounds array.

This is example of my client config: vless://81c78225-9470-44fb-9e79-e4137b9eb60d@ir.mydomain.site:443?type=tcp&path=%2F&host=fl.mydomain.site&headerType=http&security=none#VPN-409431573-169224425

This is Xray config file of my IRAN server but not working true, and all traffics is routed trough first index of outbounds array (germany server).

I also tested "domainStrategy"="IPIfNonMatch" but not working! 😢

What is the problem?? Please help me 🙏

{
  "api": {
    "services": [
      "HandlerService",
      "LoggerService",
      "StatsService"
    ],
    "tag": "api"
  },
  "inbounds": [
    {
      "listen": "127.0.0.1",
      "port": 62789,
      "protocol": "dokodemo-door",
      "settings": {
        "address": "127.0.0.1"
      },
      "tag": "api"
    }
  ],
  "log": {
    "access": "./access.log",
    "error": "./error.log",
    "loglevel": "warning"
  },
  "outbounds": [
    {
      "tag": "germany",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "de.mydomain.site",
            "port": 334,
            "users": [
              {
                "id": "390e5224-7822-4136-955b-fe95384542cc",
                "alterId": 0,
                "email": "t@t.tt",
                "security": "auto",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "wsSettings": {
          "path": "/",
          "headers": {}
        }
      }
    },
    {
      "tag": "finland",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "fl.mydomain.site",
            "port": 334,
            "users": [
              {
                "id": "390e5224-7822-4136-955b-fe95384542cc",
                "alterId": 0,
                "email": "t@t.tt",
                "security": "auto",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "wsSettings": {
          "path": "/",
          "headers": {}
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {
        "response": {
          "type": "http"
        }
      }
    }
  ],
  "policy": {
    "levels": {
      "0": {
        "statsUserDownlink": true,
        "statsUserUplink": true
      }
    },
    "system": {
      "statsInboundDownlink": true,
      "statsInboundUplink": true
    }
  },
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "blocked",
        "type": "field"
      },
      {
        "type": "field",
        "outboundTag": "blocked",
        "domain": [
          "geosite:category-ads-all",
          "ext:iran.dat:ads"
        ]
      },
      {
        "type": "field",
        "domain": [
          "fl.mydomain.site"
        ],
        "outboundTag": "finland"
      },
      {
        "type": "field",
        "domain": [
          "de.mydomain.site"
        ],
        "outboundTag": "germany"
      },
      {
        "type": "field",
        "domain": [
          "skyroom.online"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "inboundTag": [
          "api"
        ],
        "outboundTag": "direct"
      }
    ]
  },
  "stats": {}
}
hosein-moayedi commented 1 year ago

@bhoppi @rrouzbeh @ovear @digglife Please help me 🙏

qist commented 1 year ago

nginx 或者xray 的fallbacks 能帮你解决。

chika0801 commented 1 year ago

屏幕截图 2023-07-14 134647

"Host"="fl.mydomain.site", as shown in the figure, this value, cannot be used as a judgment condition for the routing rules in the Xray configuration file.

chika0801 commented 1 year ago

https://xtls.github.io/Xray-docs-next/config/routing.html#ruleobject

You can refer to the link above, which is in the Xray documentation, for an explanation of routing rule judgment conditions.

I see that in the config file you posted, the inbound part is listening on port 62789 with the free gate protocol. I'm guessing that you should have another config file that has the outbound portion of the config file that is output to your local port 62789.

If you don't have to do this, my assumption is that you'll just make changes based on the configuration file you're posting now. The inbound part would be to write a VLESS protocol combination containing say 2 user UUIDs, with different "email": "love@xray.com", parameters corresponding to the 2 user UUIDs.

The "email": "love@xray.com", parameter is then used as the user name in the routing rule match, corresponding to a different outbound configuration.

If you do not understand something, please try to modify the configuration file first, post the configuration, we look at the configuration file, more convenient to communicate.

hosein-moayedi commented 1 year ago

@chika0801

thanks for your response

I very tried to use from that doc for rules objects but did't worked. ex: I used from "attrs" or "port" and not working for me.

yes I found another config file that is:

[
  {
    "listen": "127.0.0.1",
    "port": 62789,
    "protocol": "dokodemo-door",
    "settings": {
      "address": "127.0.0.1"
    },
    "sniffing": null,
    "streamSettings": null,
    "tag": "api"
  },
  {
    "listen": null,
    "port": 443,
    "protocol": "vless",
    "settings": {
      "clients": [
        {
          "email": "409431573-169224425",
          "flow": "",
          "id": "81c78225-9470-44fb-9e79-e4137b9eb60d"
        },
        {
          "email": "1118214211-928911937",
          "flow": "",
          "id": "bdf8e282-c5bf-4fa5-aaad-fa916e7d68ac"
        },
        {
          "email": "67061441-901035391",
          "flow": "",
          "id": "0338529e-777e-4f6a-a4b5-8d4f3e65af3d"
        },
        {
          "email": "239811341-test",
          "flow": "",
          "id": "dd15541c-a097-4752-8112-f416eda5e428"
        }
      ],
      "decryption": "none",
      "fallbacks": []
    },
    "sniffing": {
      "destOverride": [
        "http",
        "tls",
        "quic"
      ],
      "enabled": false
    },
    "streamSettings": {
      "network": "tcp",
      "security": "tls",
      "tcpSettings": {
        "acceptProxyProtocol": false,
        "header": {
          "request": {
            "headers": {
              "Host": [
                "skyroom.online"
              ]
            },
            "method": "GET",
            "path": [
              "/"
            ]
          },
          "response": {
            "headers": {
              "Content-Type": [
                "application/octet-stream"
              ]
            },
            "reason": "OK",
            "status": "200",
            "version": "1.1"
          },
          "type": "http"
        }
      },
      "tlsSettings": {
        "alpn": [],
        "certificates": [
          {
            "certificateFile": "/etc/letsencrypt/live/turbo.mydomain.site/fullchain.pem",
            "keyFile": "/etc/letsencrypt/live/turbo.mydomain.site/privkey.pem"
          }
        ],
        "cipherSuites": "",
        "maxVersion": "1.3",
        "minVersion": "1.2",
        "rejectUnknownSni": true,
        "serverName": "turbo.mydomain.site",
        "settings": {
          "allowInsecure": false,
          "domains": [],
          "fingerprint": "randomized",
          "serverName": "turbo.mydomain.site"
        }
      }
    },
    "tag": "inbound-443"
  }
]
hosein-moayedi commented 1 year ago

this is my panel that I am using:

https://github.com/MHSanaei/3x-ui

chika0801 commented 1 year ago

This configuration, is what I expressed, you refer to it. But for the Xray configuration of the familiarization program, or rely on your own learning.

If there is a problem, when asking, I usually recommend to send the configuration file.

Inbound is listening on port 443, assuming a combination of VLESS+Vision+TLS protocols, and there are two user IDs, chika honoka, which correspond to EMAIL group names A and B respectively.

In the routing module, use the parameters "user": ["A"], "user": ["B"] to go to your servers in Germany and Finland.

{
    "log": {
        "loglevel": "warning"
    },
    "routing": {
        "domainStrategy": "IPIfNonMatch",
        "rules": [
            {
                "type": "field",
                "user": ["A"],
                "outboundTag": "Germany_server"
            },
            {
                "type": "field",
                "user": ["B"],
                "outboundTag": "Finlond_server"
            }
        ]
    },
    "inbounds": [
        {
            "listen": "0.0.0.0",
            "port": 443,
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "chika",
                        "email": "A",
                        "flow": "xtls-rprx-vision"
                    },
                    {
                        "id": "honoka",
                        "email": "B",
                        "flow": "xtls-rprx-vision"
                    }
                ],
                "decryption": "none",
                "fallbacks": [
                    {
                        "dest": "8001",
                        "xver": 1
                    },
                    {
                        "alpn": "h2",
                        "dest": "8002",
                        "xver": 1
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "tls",
                "tlsSettings": {
                    "rejectUnknownSni": true,
                    "minVersion": "1.2",
                    "certificates": [
                            "ocspStapling": 3600,
                            "certificateFile": "/etc/ssl/private/fullchain.cer",
                            "keyFile": "/etc/ssl/private/private.key"
                        }
                    ]
                }
            },
            "sniffing": {
                "enabled": true,
                "destOverride": [
                    "http",
                    "tls",
                    "quic"
                ]
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "", // 地址,服务端的域名或 IP;域名需确保是包含在服务端的证书中,且已正确指向了服务端的 IP
                        "port": 443, // 端口,与服务端一致
                        "users": [
                            {
                                "id": "", // 用户ID,与服务端一致
                                "encryption": "none",
                                "flow": "xtls-rprx-vision"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "tls",
                "tlsSettings": {
                    "serverName": "", // SNI,如果 "server" 填的是域名,可留空;如果 "server" 填的是 IP,填服务端的证书中包含的域名,且可不指向服务端的 IP
                    "allowInsecure": false,
                    "fingerprint": "chrome"
                }
            },
            "tag": "Germany_server"
        },
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "", // 地址,服务端的域名或 IP;域名需确保是包含在服务端的证书中,且已正确指向了服务端的 IP
                        "port": 443, // 端口,与服务端一致
                        "users": [
                            {
                                "id": "", // 用户ID,与服务端一致
                                "encryption": "none",
                                "flow": "xtls-rprx-vision"
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "tls",
                "tlsSettings": {
                    "serverName": "", // SNI,如果 "server" 填的是域名,可留空;如果 "server" 填的是 IP,填服务端的证书中包含的域名,且可不指向服务端的 IP
                    "allowInsecure": false,
                    "fingerprint": "chrome"
                }
            },
            "tag": "Finlond_server"
        }
    ]
}
us254 commented 1 year ago

Here are the key changes made in the third JSON compared to the first two:

  1. Added a "routing" section with rules to match users by "email" instead of routing by domain:
"routing": {
  "rules": [
    {
      "type": "field", 
      "user": ["A"],
      "outboundTag": "Germany_server"
    },
    {
       "type": "field",
       "user": ["B"],
       "outboundTag": "Finland_server" 
    }
  ]
}
  1. Changed inbound protocol to VLESS and defined multiple users with different "email" IDs:
"inbounds": [
  {
    "protocol": "vless",
    "settings": {
      "clients": [
        {
          "email": "A",
          "id": "user1"
        },
        {
           "email": "B",
           "id": "user2"
        }
      ]
    }
  }
]
  1. Removed domain based routing rules.

  2. Added outbound configurations to match routing tags.

So in summary, the main changes are:

This allows routing traffic based on user rather than by domain.

hosein-moayedi commented 1 year ago

@chika0801 @us254 Thanks guys for response but I want that all users can have access to both servers not spilt each user for access to one of that servers.

ex: both user A and user B should have access to each target server that want with just changing a special parameter in their client config with same port "443".

client config ----> (inbound on 443) ---- {check the special parameter in client config} ----> GERMANY SERVER
                                                          | or
                                                          ----> FINLAND SERVER

all client config paramters should be same like port and domain and etc... but should there is a special parameter in part of client config that I don't know where. (like HOST parameter in http header but this is not working)

chika0801 commented 1 year ago

I think the most convenient solution for the particular parameter you're building, at the moment, I think, is to have a different UUID, i.e. the example I gave earlier in my reply to you.

You create, on the client side, 2 configurations, which only have different UUIDs, to differentiate which country's server to connect to.

As far as I know, there is no other special parameter in Xray that you're looking for that can do this.

All the parameters inside your client configuration are the same, except the UUID is different, which I think is the most convenient and fastest way.

hosein-moayedi commented 1 year ago

thanks @chika0801 that is good suggestion

hosein-moayedi commented 1 year ago
Screenshot 2023-07-18 at 7 19 49 AM

@chika0801 I have an idea. is it possible to use regex in the user part? I mean I can make 2 configs for the user with the different uuid and the same first part of the email and just make a difference in the second part of the email, that second part pointing to the target server?

like this:

Jake has 2 configs: config 1) email is "jake-de" config 2) email is "jake-fl",

all other info is like port and inbound is same and just the secound part (after -) is important to route the user to the target server.

If we can using from regex in the user part of this screenshot we can do it very easy 😋

chika0801 commented 1 year ago

The reason this parameter of email can be different is because, you have different UUIDs in the server-side configuration.

                "clients": [
                    {
                        "id": "chika",
                        "email": "A",
                        "flow": "xtls-rprx-vision"
                    },
                    {
                        "id": "honoka",
                        "email": "B",
                        "flow": "xtls-rprx-vision"
                    }
                ],

Think of it another way, if you look at the parameters in the client configuration file, there is no EMAIL as an item value in what to fill in.

Your demand is the client configuration file as much as possible the same, so I have been saying that I can only think of, in the client configuration, replace the UUID, other than to keep the same, is the most convenient!

chika0801 commented 1 year ago

have an idea. is it possible to use regex in the user part? I mean I can make 2 configs for the user with the different uuid and the same first part of the email and just make a difference in the second part of the email, that second part pointing to the target server?

like this:

Jake has 2 configs: config 1) email is "jake-de" config 2) email is "jake-fl",

all other info is like port and inbound is same and just the secound part (after -) is important to route the user to the target server.

If we can using from regex in the user part of this screenshot we can do it very easy 😋

I used the flip wall, but I didn't fully understand the idea you expressed. If you can add more words, it can be easier to communicate.

us254 commented 1 year ago

To achieve your goal of routing clients to different target servers based on the "email" part of the configuration, you can still use the approach suggested earlier, which involves creating different UUIDs for each target server. In this way, clients can choose the appropriate configuration based on the UUID, and all other configuration details can remain the same.

For example, you can create two client configurations for Jake as follows:

Config 1:

{
  "id": "jake-de",
  "email": "jake@de",
  "flow": "xtls-rprx-vision",
  "otherConfigParams": "..."
}

Config 2:

{
  "id": "jake-fl",
  "email": "jake@fl",
  "flow": "xtls-rprx-vision",
  "otherConfigParams": "..."
}

In this case, both configurations are identical, except for the "id" and "email" parts. When Jake uses the first configuration (with "jake-de" as the "id"), he will be routed to the Germany server, and when he uses the second configuration (with "jake-fl" as the "id"), he will be routed to the Finland server.

While this approach requires separate configurations for each target server, it still achieves the desired outcome without the need for regex in the user part.