feat: Add use sni as host (#1516)

* feat: Add use sni as host

* check if there is any sni
This commit is contained in:
Mohammad
2024-12-15 14:31:32 +03:30
committed by GitHub
parent c05ba174f6
commit 5c217e9694
11 changed files with 72 additions and 7 deletions

View File

@@ -37,6 +37,7 @@
"hostsDialog.addHost": "Add host",
"hostsDialog.advancedOptions": "Advanced options",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.useSniAsHost": "Use sni as host",
"hostsDialog.alpn": "ALPN",
"hostsDialog.apply": "Apply",
"hostsDialog.currentServer": "IP Address of current server",

View File

@@ -42,6 +42,7 @@
"hostsDialog.addHost": "افزودن هاست",
"hostsDialog.advancedOptions": "تنظیمات پیشرفته",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.useSniAsHost": "استفاده از sni به عنوان هاست",
"hostsDialog.alpn": "ALPN",
"hostsDialog.apply": "اعمال",
"hostsDialog.currentServer": "IP کنونی سرور",

View File

@@ -37,6 +37,7 @@
"hostsDialog.addHost": "Добавить хост",
"hostsDialog.advancedOptions": "Дополнительные опции",
"hostsDialog.allowinsecure": "Allow Insecure",
"hostsDialog.useSniAsHost": "Use sni as host",
"hostsDialog.alpn": "ALPN",
"hostsDialog.apply": "Применить",
"hostsDialog.currentServer": "IP текущего сервера",
@@ -188,4 +189,4 @@
"usersTable.noUserMatched": "Похоже, нет пользователя, соответствующего вашему запросу",
"usersTable.status": "Статус",
"usersTable.total": "Всего"
}
}

View File

@@ -37,6 +37,7 @@
"hostsDialog.addHost": "添加主机",
"hostsDialog.advancedOptions": "高级选项",
"hostsDialog.allowinsecure": "允许不安全连接",
"hostsDialog.useSniAsHost": "Use sni as host",
"hostsDialog.alpn": "ALPN",
"hostsDialog.apply": "保存",
"hostsDialog.currentServer": "当前服务器的 IP 地址",
@@ -189,4 +190,4 @@
"usersTable.status": "状态",
"usersTable.sortByExpire": "按过期时间排序",
"usersTable.total": "总共"
}
}

View File

@@ -152,6 +152,7 @@ const hostsSchema = z.record(
security: z.string(),
alpn: z.string(),
fingerprint: z.string(),
use_sni_as_host: z.boolean().default(false),
})
)
);
@@ -212,6 +213,7 @@ const AccordionInbound: FC<AccordionInboundType> = ({
security: "inbound_default",
alpn: "",
fingerprint: "",
use_sni_as_host: false,
});
};
const duplicateHost = (index: number) => {
@@ -1067,6 +1069,33 @@ const AccordionInbound: FC<AccordionInboundType> = ({
<FormControl
isInvalid={
!!(
accordionErrors &&
accordionErrors[index]?.use_sni_as_host
)
}
>
<Checkbox
{...form.register(
hostKey + "." + index + ".use_sni_as_host"
)}
>
<FormLabel>
{t("hostsDialog.useSniAsHost")}
</FormLabel>
</Checkbox>
{accordionErrors &&
accordionErrors[index]?.use_sni_as_host && (
<Error>
{
accordionErrors[index]?.use_sni_as_host
?.message
}
</Error>
)}
</FormControl>
<FormControl
isInvalid={
!!(
accordionErrors &&

View File

@@ -158,6 +158,7 @@ def update_hosts(db: Session, inbound_tag: str, modified_hosts: List[ProxyHostMo
fragment_setting=host.fragment_setting,
noise_setting=host.noise_setting,
random_user_agent=host.random_user_agent,
use_sni_as_host=host.use_sni_as_host,
) for host in modified_hosts
]
db.commit()

View File

@@ -0,0 +1,27 @@
"""add use sni as host to hosts
Revision ID: 2b231de97dc3
Revises: e7b869e999b4
Create Date: 2024-12-15 09:48:24.330959
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '2b231de97dc3'
down_revision = 'e7b869e999b4'
branch_labels = None
depends_on = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('hosts', sa.Column('use_sni_as_host', sa.Boolean(), server_default='0', nullable=False))
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('hosts', 'use_sni_as_host')
# ### end Alembic commands ###

View File

@@ -263,6 +263,7 @@ class ProxyHost(Base):
fragment_setting = Column(String(100), nullable=True)
noise_setting = Column(String(2000), nullable=True)
random_user_agent = Column(Boolean, nullable=False, default=False, server_default='0')
use_sni_as_host = Column(Boolean, nullable=False, default=False, server_default="0")
class System(Base):

View File

@@ -4,7 +4,7 @@ from enum import Enum
from typing import Optional, Union
from uuid import UUID, uuid4
from pydantic import field_validator, ConfigDict, BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field, field_validator
from app.utils.system import random_password
from xray_api.types.account import (
@@ -13,7 +13,7 @@ from xray_api.types.account import (
TrojanAccount,
VLESSAccount,
VMessAccount,
XTLSFlows
XTLSFlows,
)
FRAGMENT_PATTERN = re.compile(r'^((\d{1,4}-\d{1,4})|(\d{1,4})),((\d{1,3}-\d{1,3})|(\d{1,3})),(tlshello|\d|\d\-\d)$')
@@ -154,6 +154,7 @@ class ProxyHost(BaseModel):
fragment_setting: Optional[str] = Field(None, nullable=True)
noise_setting: Optional[str] = Field(None, nullable=True)
random_user_agent: Union[bool, None] = None
use_sni_as_host: Union[bool, None] = None
model_config = ConfigDict(from_attributes=True)
@field_validator("remark", mode="after")

View File

@@ -292,6 +292,9 @@ def process_inbounds_and_tags(
else:
path = inbound.get("path", "").format_map(format_variables)
if host.get("use_sni_as_host", False) and sni:
req_host = sni
host_inbound.update(
{
"port": host["port"] or inbound["port"],

View File

@@ -10,10 +10,8 @@ from app.xray.core import XRayCore
from app.xray.node import XRayNode
from config import XRAY_ASSETS_PATH, XRAY_EXECUTABLE_PATH, XRAY_JSON
from xray_api import XRay as XRayAPI
from xray_api import exceptions
from xray_api import exceptions, types
from xray_api import exceptions as exc
from xray_api import types
core = XRayCore(XRAY_EXECUTABLE_PATH, XRAY_ASSETS_PATH)
@@ -64,6 +62,7 @@ def hosts(storage: dict):
"fragment_setting": host.fragment_setting,
"noise_setting": host.noise_setting,
"random_user_agent": host.random_user_agent,
"use_sni_as_host": host.use_sni_as_host,
} for host in inbound_hosts if not host.is_disabled
]