Gozargah / Marzban

Unified GUI Censorship Resistant Solution Powered by Xray
https://t.me/gozargah_marzban
GNU Affero General Public License v3.0
3.24k stars 457 forks source link

Multi Outbound Routing #1220

Open fodhelper opened 1 month ago

fodhelper commented 1 month ago

Hello I know all of you have warp outbound, some people have even more If we want to have multiple config (one to freedom, another to warp and another for others) we need to create multiple Inbounds and add routing like this

{
  "inbounds": [
    {
      "tag": "direct-in",
      "protocol": "vless",
      "port": 100,
      "settings": {
        "clients": [],
        "decryption": "none"
      },
      "streamSettings": {}
    },
    {
      "tag": "warp-in",
      "protocol": "vless",
      "port": 101,
      "settings": {
        "clients": [],
        "decryption": "none"
      },
      "streamSettings": {}
    },
    {
      "tag": "other-in",
      "protocol": "vless",
      "port": 102,
      "settings": {
        "clients": [],
        "decryption": "none"
      },
      "streamSettings": {}
    }
  ],
  "outbounds": [
    {
      "tag": "warp-out",
      "protocol": "wireguard",
      "settings": {}
    },
    {
      "tag": "other-out",
      "protocol": "xxx"
    }
  ],
  "routing": {
    "rules": [
      {
        "inboundTag": [
          "warp-in"
        ],
        "outboundTag": "warp-out"
      },
      {
        "inboundTag": [
          "other-in"
        ],
        "outboundTag": "other-out"
      }
    ]
  }
}

But there is another way to do the same without creating a new inbound for each outbound

{
  "inbounds": [
    {
      "protocol": "vless",
      "port": 443,
      "settings": {
        "clients": [
          {
            "id": "4d0eb5f1-6bb0-44a7-8ee8-eafdc1e1c933",
            "flow": "xtls-rprx-vision",
            "level": 0,
            "email": "direct@xray.com"
          },
          {
            "id": "efb37094-ac71-4a51-9bcd-8956638e4d92",
            "flow": "xtls-rprx-vision",
            "level": 0,
            "email": "warp@xray.com"
          },
          {
            "id": "23c1d289-d353-4bff-a0b9-545bfa0d517d",
            "flow": "xtls-rprx-vision",
            "level": 0,
            "email": "other@xray.com"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {}
    }
  ],
  "outbounds": [
    {
      "tag": "warp",
      "protocol": "wireguard",
      "settings": {}
    },
    {
      "tag": "other",
      "protocol": "xxx"
    }
  ],
  "routing": {
    "rules": [
      {
        "user": [
          "warp@xray.com"
        ],
        "outboundTag": "warp"
      },
      {
        "user": [
          "other@xray.com"
        ],
        "outboundTag": "other"
      }
    ]
  }
}

It has many benefits especially for users who have multiple outbounds Is it possible to integrate this with Marzban? @SaintShit Needs to create new pair of Email and UUID for each outbound and a change in GUI to select the outbound for each Host

M03ED commented 1 month ago

This is gonna add much complexity, and needs lots of change in database structure. Even if this is possible, it's not worth this much change and complexity.

fodhelper commented 1 month ago

Yes, it needs a lot of changes, but there may be an easier solution I'm trying to find it

fodhelper commented 1 month ago

First thing is that, we don't need to create many UUID for each user, we can just append the Outbound name to user's UUID and then change this string to a new UUID! (user's UUID will become a master UUID)

import uuid

def str_to_uuid(input_string):
    return uuid.uuid5(uuid.UUID('00000000-0000-0000-0000-000000000000'), input_string)

print( str_to_uuid("4d0eb5f1-6bb0-44a7-8ee8-eafdc1e1c933_warp") )

or we can directly use user's UUID as namespace of UUIDv5

import uuid

print( uuid.uuid5(uuid.UUID('4d0eb5f1-6bb0-44a7-8ee8-eafdc1e1c933'), 'warp') )

for Trojan Inbounds, can just append outbound name

M03ED commented 1 month ago

First thing is that, we don't need to create many UUID for each user, we can just append the Outbound name to user's UUID and then change this string to a new UUID! (user's UUID will become a master UUID)

import uuid

def str_to_uuid(input_string):
    return uuid.uuid5(uuid.UUID('00000000-0000-0000-0000-000000000000'), input_string)

print( str_to_uuid("4d0eb5f1-6bb0-44a7-8ee8-eafdc1e1c933_warp") )

or we can directly use user's UUID as namespace of UUIDv5

import uuid

print( uuid.uuid5(uuid.UUID('4d0eb5f1-6bb0-44a7-8ee8-eafdc1e1c933'), 'warp') )

for Trojan Inbounds, can just append outbound name

This part is not a big problem, the real problem is the record usage job, we're gonna have multiple records for each user instead of 1, also this gonna be applied for each node

fodhelper commented 1 month ago

record usage job only uses user-id and ignores rest of the email, so we can just add outbound name after the username and there will be no problem https://github.com/Gozargah/Marzban/blob/349451da0de5f590f19b4a84b865ed376aacef63/app/jobs/record_usages.py#L104-L110 just needs changes in add/remove/alter/update users at api operations https://github.com/Gozargah/Marzban/blob/master/app/xray/operations.py

M03ED commented 1 month ago

record usage job only uses user-id and ignores rest of the email, so we can just add outbound name after the username and there will be no problem

https://github.com/Gozargah/Marzban/blob/349451da0de5f590f19b4a84b865ed376aacef63/app/jobs/record_usages.py#L104-L110

just needs changes in add/remove/alter/update users at api operations https://github.com/Gozargah/Marzban/blob/master/app/xray/operations.py

i think i didn't says it right, i mean job its gonna be much slower and its not efficient

fodhelper commented 1 month ago

The only thing that can take longer time is recording new values to database because there will be multiple records for every single user But this can get optimized by combining all records of same uid before writing the new data usage to the database and not all users gonna add 10 outbounds, mostly will only add warp outbound and done, so even if it's a problem, it's for less than 5% of Marzban users