120 lines
4.1 KiB
Python
120 lines
4.1 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from .model import Hy2Endpoint
|
|
from .policy import Policy
|
|
from .version import SUPPORTED_SING_BOX_VERSION
|
|
|
|
TARGET_VERSION = SUPPORTED_SING_BOX_VERSION
|
|
GECKO_MIN_PACKET_SIZE = 512
|
|
GECKO_MAX_PACKET_SIZE = 1200
|
|
|
|
|
|
def render_config(policy: Policy, endpoint: Hy2Endpoint) -> dict[str, Any]:
|
|
network = policy.network
|
|
dns = policy.dns
|
|
outbound: dict[str, Any] = {
|
|
"type": "hysteria2",
|
|
"tag": "hy2-out",
|
|
"server": endpoint.server,
|
|
"up_mbps": policy.bandwidth.up_mbps,
|
|
"down_mbps": policy.bandwidth.down_mbps,
|
|
"password": endpoint.password,
|
|
"tls": {
|
|
"enabled": True,
|
|
"server_name": endpoint.sni,
|
|
"insecure": endpoint.insecure,
|
|
},
|
|
"disable_chrome_parrot": False,
|
|
"bind_interface": network.upstream_interface,
|
|
"domain_resolver": {"server": "bootstrap-dns", "strategy": dns.strategy},
|
|
}
|
|
if endpoint.server_port is not None:
|
|
outbound["server_port"] = endpoint.server_port
|
|
else:
|
|
outbound["server_ports"] = list(endpoint.server_ports)
|
|
if endpoint.obfs_type is not None:
|
|
obfs: dict[str, Any] = {
|
|
"type": endpoint.obfs_type,
|
|
"password": endpoint.obfs_password,
|
|
}
|
|
if endpoint.obfs_type == "gecko":
|
|
obfs["min_packet_size"] = GECKO_MIN_PACKET_SIZE
|
|
obfs["max_packet_size"] = GECKO_MAX_PACKET_SIZE
|
|
outbound["obfs"] = obfs
|
|
|
|
return {
|
|
"log": {"level": "info", "timestamp": True},
|
|
"dns": {
|
|
"servers": [
|
|
{
|
|
"type": "udp",
|
|
"tag": "bootstrap-dns",
|
|
"server": dns.bootstrap_server,
|
|
"server_port": dns.bootstrap_port,
|
|
"bind_interface": network.upstream_interface,
|
|
},
|
|
{
|
|
"type": "https",
|
|
"tag": "remote-dns",
|
|
"server": dns.remote_server,
|
|
"server_port": dns.remote_port,
|
|
"path": dns.remote_path,
|
|
"tls": {
|
|
"enabled": True,
|
|
"server_name": dns.remote_tls_server_name,
|
|
},
|
|
"detour": "hy2-out",
|
|
},
|
|
],
|
|
"final": "remote-dns",
|
|
"strategy": dns.strategy,
|
|
},
|
|
"inbounds": [
|
|
{
|
|
"type": "tun",
|
|
"tag": "tun-in",
|
|
"interface_name": network.tun_name,
|
|
"address": [network.tun_address],
|
|
"mtu": network.mtu,
|
|
"dns_mode": "disabled",
|
|
"auto_route": True,
|
|
"iproute2_table_index": network.iproute2_table_index,
|
|
"iproute2_rule_index": network.iproute2_rule_index,
|
|
"auto_redirect": True,
|
|
"auto_redirect_input_mark": network.auto_redirect_input_mark,
|
|
"auto_redirect_output_mark": network.auto_redirect_output_mark,
|
|
"auto_redirect_reset_mark": network.auto_redirect_reset_mark,
|
|
"auto_redirect_nfqueue": network.auto_redirect_nfqueue,
|
|
"auto_redirect_iproute2_fallback_rule_index": network.auto_redirect_fallback_rule_index,
|
|
"strict_route": True,
|
|
"stack": "mixed",
|
|
"route_exclude_address": list(network.route_exclude_address),
|
|
}
|
|
],
|
|
"outbounds": [outbound],
|
|
"route": {
|
|
"auto_detect_interface": True,
|
|
"default_domain_resolver": {
|
|
"server": "bootstrap-dns",
|
|
"strategy": dns.strategy,
|
|
},
|
|
"final": "hy2-out",
|
|
"rules": [
|
|
{
|
|
"network": ["tcp", "udp"],
|
|
"port": 53,
|
|
"action": "hijack-dns",
|
|
}
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
def render_bytes(policy: Policy, endpoint: Hy2Endpoint) -> bytes:
|
|
return (
|
|
json.dumps(render_config(policy, endpoint), ensure_ascii=False, indent=2) + "\n"
|
|
).encode("utf-8")
|