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

Multi Outbound Routing #1220

Closed
fodhelper opened this issue Aug 4, 2024 · 8 comments
Closed

Multi Outbound Routing #1220

fodhelper opened this issue Aug 4, 2024 · 8 comments
Labels
Core Feature New feature or request

Comments

@fodhelper
Copy link
Contributor

fodhelper commented Aug 4, 2024

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": "[email protected]"
          },
          {
            "id": "efb37094-ac71-4a51-9bcd-8956638e4d92",
            "flow": "xtls-rprx-vision",
            "level": 0,
            "email": "[email protected]"
          },
          {
            "id": "23c1d289-d353-4bff-a0b9-545bfa0d517d",
            "flow": "xtls-rprx-vision",
            "level": 0,
            "email": "[email protected]"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {}
    }
  ],
  "outbounds": [
    {
      "tag": "warp",
      "protocol": "wireguard",
      "settings": {}
    },
    {
      "tag": "other",
      "protocol": "xxx"
    }
  ],
  "routing": {
    "rules": [
      {
        "user": [
          "[email protected]"
        ],
        "outboundTag": "warp"
      },
      {
        "user": [
          "[email protected]"
        ],
        "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

@fodhelper fodhelper added the Feature New feature or request label Aug 4, 2024
@M03ED
Copy link
Collaborator

M03ED commented Aug 4, 2024

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
Copy link
Contributor Author

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

@fodhelper
Copy link
Contributor Author

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
Copy link
Collaborator

M03ED commented Aug 5, 2024

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
Copy link
Contributor Author

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

def get_users_stats(api: XRayAPI):
try:
params = defaultdict(int)
for stat in filter(attrgetter('value'), api.get_users_stats(reset=True, timeout=30)):
params[stat.name.split('.', 1)[0]] = stat.value
params = list({"uid": uid, "value": value} for uid, value in params.items())
return params

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

@M03ED
Copy link
Collaborator

M03ED commented Aug 5, 2024

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

def get_users_stats(api: XRayAPI):
try:
params = defaultdict(int)
for stat in filter(attrgetter('value'), api.get_users_stats(reset=True, timeout=30)):
params[stat.name.split('.', 1)[0]] = stat.value
params = list({"uid": uid, "value": value} for uid, value in params.items())
return params

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
Copy link
Contributor Author

fodhelper commented Aug 5, 2024

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

@erfjab erfjab added the Backend label Aug 7, 2024
@M03ED M03ED removed their assignment Aug 7, 2024
@erfjab erfjab added Core and removed Backend labels Sep 1, 2024
@M03ED
Copy link
Collaborator

M03ED commented Oct 12, 2024

not for now , maybe in future.

@M03ED M03ED closed this as not planned Won't fix, can't repro, duplicate, stale Oct 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Core Feature New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants