mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-08-21 14:37:16 +00:00
Xray init support
This commit is contained in:
15
vpn/xray_api/protocols/__init__.py
Normal file
15
vpn/xray_api/protocols/__init__.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Protocol-specific implementations for Xray Manager.
|
||||
"""
|
||||
|
||||
from .base import BaseProtocol
|
||||
from .vless import VlessProtocol
|
||||
from .vmess import VmessProtocol
|
||||
from .trojan import TrojanProtocol
|
||||
|
||||
__all__ = [
|
||||
"BaseProtocol",
|
||||
"VlessProtocol",
|
||||
"VmessProtocol",
|
||||
"TrojanProtocol"
|
||||
]
|
45
vpn/xray_api/protocols/base.py
Normal file
45
vpn/xray_api/protocols/base.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""
|
||||
Base protocol implementation.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List, Dict, Any, Optional
|
||||
from ..models import User
|
||||
|
||||
|
||||
class BaseProtocol(ABC):
|
||||
"""Base class for all protocol implementations."""
|
||||
|
||||
def __init__(self, port: int, tag: Optional[str] = None, listen: str = "0.0.0.0", network: str = "tcp"):
|
||||
self.port = port
|
||||
self.tag = tag or self._default_tag()
|
||||
self.listen = listen
|
||||
self.network = network
|
||||
|
||||
@abstractmethod
|
||||
def _default_tag(self) -> str:
|
||||
"""Return default tag for this protocol."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def create_inbound_config(self, users: List[User]) -> Dict[str, Any]:
|
||||
"""Create inbound configuration for this protocol."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def create_user_config(self, user: User) -> Dict[str, Any]:
|
||||
"""Create user configuration for adding to existing inbound."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def generate_client_link(self, user: User, hostname: str) -> str:
|
||||
"""Generate client connection link."""
|
||||
pass
|
||||
|
||||
def _base_inbound_config(self) -> Dict[str, Any]:
|
||||
"""Common inbound configuration."""
|
||||
return {
|
||||
"listen": self.listen,
|
||||
"port": self.port,
|
||||
"tag": self.tag
|
||||
}
|
80
vpn/xray_api/protocols/trojan.py
Normal file
80
vpn/xray_api/protocols/trojan.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
Trojan protocol implementation.
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Any, Optional
|
||||
from .base import BaseProtocol
|
||||
from ..models import User, TrojanUser
|
||||
from ..utils import generate_self_signed_cert, pem_to_lines
|
||||
from ..exceptions import CertificateError
|
||||
|
||||
|
||||
class TrojanProtocol(BaseProtocol):
|
||||
"""Trojan protocol handler."""
|
||||
|
||||
def __init__(self, port: int, tag: Optional[str] = None, listen: str = "0.0.0.0",
|
||||
network: str = "tcp", cert_pem: Optional[str] = None,
|
||||
key_pem: Optional[str] = None, hostname: str = "localhost"):
|
||||
super().__init__(port, tag, listen, network)
|
||||
self.hostname = hostname
|
||||
|
||||
if cert_pem and key_pem:
|
||||
self.cert_pem = cert_pem
|
||||
self.key_pem = key_pem
|
||||
else:
|
||||
# Generate self-signed certificate
|
||||
self.cert_pem, self.key_pem = generate_self_signed_cert(hostname)
|
||||
|
||||
def _default_tag(self) -> str:
|
||||
return "trojan-inbound"
|
||||
|
||||
def create_inbound_config(self, users: List[TrojanUser]) -> Dict[str, Any]:
|
||||
"""Create Trojan inbound configuration."""
|
||||
config = self._base_inbound_config()
|
||||
config.update({
|
||||
"protocol": "trojan",
|
||||
"settings": {
|
||||
"_TypedMessage_": "xray.proxy.trojan.Config",
|
||||
"clients": [self._user_to_client(user) for user in users],
|
||||
"fallbacks": [{"dest": 80}]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": self.network,
|
||||
"security": "tls",
|
||||
"tlsSettings": {
|
||||
"alpn": ["http/1.1"],
|
||||
"certificates": [{
|
||||
"certificate": pem_to_lines(self.cert_pem),
|
||||
"key": pem_to_lines(self.key_pem),
|
||||
"usage": "encipherment"
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
return {"inbounds": [config]}
|
||||
|
||||
def create_user_config(self, user: TrojanUser) -> Dict[str, Any]:
|
||||
"""Create user configuration for Trojan."""
|
||||
return {
|
||||
"inboundTag": self.tag,
|
||||
"proxySettings": {
|
||||
"_TypedMessage_": "xray.proxy.trojan.Config",
|
||||
"clients": [self._user_to_client(user)]
|
||||
}
|
||||
}
|
||||
|
||||
def generate_client_link(self, user: TrojanUser, hostname: str) -> str:
|
||||
"""Generate Trojan client link."""
|
||||
return f"trojan://{user.password}@{hostname}:{self.port}#{user.email}"
|
||||
|
||||
def get_client_note(self) -> str:
|
||||
"""Get note for client configuration when using self-signed certificates."""
|
||||
return "Add 'allowInsecure: true' to TLS settings for self-signed certificates"
|
||||
|
||||
def _user_to_client(self, user: TrojanUser) -> Dict[str, Any]:
|
||||
"""Convert TrojanUser to client configuration."""
|
||||
return {
|
||||
"password": user.password,
|
||||
"level": user.level,
|
||||
"email": user.email
|
||||
}
|
55
vpn/xray_api/protocols/vless.py
Normal file
55
vpn/xray_api/protocols/vless.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""
|
||||
VLESS protocol implementation.
|
||||
"""
|
||||
|
||||
from typing import List, Dict, Any, Optional
|
||||
from .base import BaseProtocol
|
||||
from ..models import User, VlessUser
|
||||
|
||||
|
||||
class VlessProtocol(BaseProtocol):
|
||||
"""VLESS protocol handler."""
|
||||
|
||||
def __init__(self, port: int, tag: Optional[str] = None, listen: str = "0.0.0.0", network: str = "tcp"):
|
||||
super().__init__(port, tag, listen, network)
|
||||
|
||||
def _default_tag(self) -> str:
|
||||
return "vless-inbound"
|
||||
|
||||
def create_inbound_config(self, users: List[VlessUser]) -> Dict[str, Any]:
|
||||
"""Create VLESS inbound configuration."""
|
||||
config = self._base_inbound_config()
|
||||
config.update({
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"_TypedMessage_": "xray.proxy.vless.inbound.Config",
|
||||
"clients": [self._user_to_client(user) for user in users],
|
||||
"decryption": "none"
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": self.network
|
||||
}
|
||||
})
|
||||
return {"inbounds": [config]}
|
||||
|
||||
def create_user_config(self, user: VlessUser) -> Dict[str, Any]:
|
||||
"""Create user configuration for VLESS."""
|
||||
return {
|
||||
"inboundTag": self.tag,
|
||||
"proxySettings": {
|
||||
"_TypedMessage_": "xray.proxy.vless.inbound.Config",
|
||||
"clients": [self._user_to_client(user)]
|
||||
}
|
||||
}
|
||||
|
||||
def generate_client_link(self, user: VlessUser, hostname: str) -> str:
|
||||
"""Generate VLESS client link."""
|
||||
return f"vless://{user.uuid}@{hostname}:{self.port}?encryption=none&type={self.network}#{user.email}"
|
||||
|
||||
def _user_to_client(self, user: VlessUser) -> Dict[str, Any]:
|
||||
"""Convert VlessUser to client configuration."""
|
||||
return {
|
||||
"id": user.uuid,
|
||||
"level": user.level,
|
||||
"email": user.email
|
||||
}
|
73
vpn/xray_api/protocols/vmess.py
Normal file
73
vpn/xray_api/protocols/vmess.py
Normal file
@@ -0,0 +1,73 @@
|
||||
"""
|
||||
VMess protocol implementation.
|
||||
"""
|
||||
|
||||
import json
|
||||
import base64
|
||||
from typing import List, Dict, Any, Optional
|
||||
from .base import BaseProtocol
|
||||
from ..models import User, VmessUser
|
||||
|
||||
|
||||
class VmessProtocol(BaseProtocol):
|
||||
"""VMess protocol handler."""
|
||||
|
||||
def __init__(self, port: int, tag: Optional[str] = None, listen: str = "0.0.0.0", network: str = "tcp"):
|
||||
super().__init__(port, tag, listen, network)
|
||||
|
||||
def _default_tag(self) -> str:
|
||||
return "vmess-inbound"
|
||||
|
||||
def create_inbound_config(self, users: List[VmessUser]) -> Dict[str, Any]:
|
||||
"""Create VMess inbound configuration."""
|
||||
config = self._base_inbound_config()
|
||||
config.update({
|
||||
"protocol": "vmess",
|
||||
"settings": {
|
||||
"_TypedMessage_": "xray.proxy.vmess.inbound.Config",
|
||||
"clients": [self._user_to_client(user) for user in users]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": self.network
|
||||
}
|
||||
})
|
||||
return {"inbounds": [config]}
|
||||
|
||||
def create_user_config(self, user: VmessUser) -> Dict[str, Any]:
|
||||
"""Create user configuration for VMess."""
|
||||
return {
|
||||
"inboundTag": self.tag,
|
||||
"proxySettings": {
|
||||
"_TypedMessage_": "xray.proxy.vmess.inbound.Config",
|
||||
"clients": [self._user_to_client(user)]
|
||||
}
|
||||
}
|
||||
|
||||
def generate_client_link(self, user: VmessUser, hostname: str) -> str:
|
||||
"""Generate VMess client link."""
|
||||
config = {
|
||||
"v": "2",
|
||||
"ps": user.email,
|
||||
"add": hostname,
|
||||
"port": str(self.port),
|
||||
"id": user.uuid,
|
||||
"aid": str(user.alter_id),
|
||||
"net": self.network,
|
||||
"type": "none",
|
||||
"host": "",
|
||||
"path": "",
|
||||
"tls": ""
|
||||
}
|
||||
|
||||
config_json = json.dumps(config, separators=(',', ':'))
|
||||
encoded = base64.b64encode(config_json.encode()).decode()
|
||||
return f"vmess://{encoded}"
|
||||
|
||||
def _user_to_client(self, user: VmessUser) -> Dict[str, Any]:
|
||||
"""Convert VmessUser to client configuration."""
|
||||
return {
|
||||
"id": user.uuid,
|
||||
"alterId": user.alter_id,
|
||||
"level": user.level,
|
||||
"email": user.email
|
||||
}
|
Reference in New Issue
Block a user