Files
LorenEteval_Furious/Furious/Backends/Xray/TUN.py
T
2026-08-12 12:20:47 +08:00

156 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Copyright (C) 2024–present Loren Eteval & contributors <loren.eteval@proton.me>
#
# This file is part of Furious.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""Store and apply Xray-core native TUN settings."""
from __future__ import annotations
from Furious.Frozenlib import *
import copy
import json
__all__ = [
'DEFAULT_XRAY_TUN_SETTINGS',
'buildXrayTUNInbound',
'getXrayTUNSettings',
'hasXrayTUNInbound',
'isXrayTUNEnabled',
'saveXrayTUNSettings',
'setXrayTUNEnabled',
]
DEFAULT_XRAY_TUN_SETTINGS = {
'name': '',
'desc': '',
'mtu': 1500,
'gateway': ['10.0.0.1/16', 'fc00::1/64'],
'dns': ['1.1.1.1', '8.8.8.8'],
'userLevel': 0,
'autoSystemRoutingTable': ['0.0.0.0/0', '::/0'],
'autoOutboundsInterface': 'auto',
}
registerAppSettings('useXrayTUN', isBinary=True, default=AppBinarySettings.ON_)
registerAppSettings('XrayTUNSettings')
def isXrayTUNEnabled() -> bool:
"""Return whether Xray-core should provide TUN mode."""
return AppSettings.isStateON_('useXrayTUN')
def setXrayTUNEnabled(enabled: bool):
"""Persist whether Xray-core should provide TUN mode."""
AppSettings.set(
'useXrayTUN',
AppBinarySettings.ON_ if enabled else AppBinarySettings.OFF,
)
def _normalizedXrayTUNSettings(settings) -> dict:
"""Return validated Xray TUN settings with defaults for invalid fields."""
result = copy.deepcopy(DEFAULT_XRAY_TUN_SETTINGS)
if not isinstance(settings, dict):
return result
for key in ('name', 'desc', 'autoOutboundsInterface'):
value = settings.get(key)
if isinstance(value, str):
result[key] = value.strip()
for key in ('gateway', 'dns', 'autoSystemRoutingTable'):
value = settings.get(key)
if isinstance(value, (list, tuple)):
result[key] = [
item.strip() for item in value if isinstance(item, str) and item.strip()
]
mtu = settings.get('mtu')
if isinstance(mtu, int) and not isinstance(mtu, bool) and mtu > 0:
result['mtu'] = mtu
userLevel = settings.get('userLevel')
if (
isinstance(userLevel, int)
and not isinstance(userLevel, bool)
and userLevel >= 0
):
result['userLevel'] = userLevel
return result
def getXrayTUNSettings() -> dict:
"""Return a validated copy of the persisted Xray TUN settings."""
try:
settings = json.loads(AppSettings.get('XrayTUNSettings'))
except Exception:
# Any non-exit exceptions
settings = None
return _normalizedXrayTUNSettings(settings)
def saveXrayTUNSettings(settings: dict):
"""Validate and persist Xray TUN settings."""
AppSettings.set(
'XrayTUNSettings',
json.dumps(_normalizedXrayTUNSettings(settings), ensure_ascii=False),
)
def buildXrayTUNInbound(settings=None) -> dict:
"""Build an Xray TUN inbound from persisted or supplied settings."""
settings = _normalizedXrayTUNSettings(
getXrayTUNSettings() if settings is None else settings
)
settings = {
key: value for key, value in settings.items() if value != '' and value != []
}
return {
'tag': 'tun',
'protocol': 'tun',
'settings': settings,
'sniffing': {
'enabled': True,
'destOverride': ['http', 'tls', 'quic'],
},
}
def hasXrayTUNInbound(config) -> bool:
"""Return whether an Xray configuration contains a TUN inbound."""
inbounds = config.get('inbounds', [])
if not isinstance(inbounds, list):
return False
return any(
isinstance(inbound, dict)
and str(inbound.get('protocol', '')).casefold() == 'tun'
for inbound in inbounds
)