123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- import 'dart:io';
- import 'package:speed_safe/app/server/hysteria/server.dart';
- import 'package:speed_safe/app/server/shadowsocks/server.dart';
- import 'package:speed_safe/app/server/sing-box/config.dart';
- import 'package:speed_safe/app/server/trojan/server.dart';
- import 'package:speed_safe/app/server/xray/config.dart' as xray_config;
- import 'package:speed_safe/app/server/xray/server.dart';
- import 'package:speed_safe/app/server/server_base.dart';
- import 'package:speed_safe/app/util/system.dart';
- import 'package:path/path.dart' as p;
- class SingBoxGenerate {
- static const ipRegExp = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
- static Future<String> resolveDns(String dns) async {
- final dnsHost = Uri.parse(dns).host;
- if (!RegExp(ipRegExp).hasMatch(dnsHost) && dnsHost.isNotEmpty) {
- try {
- final dnsIp = (await InternetAddress.lookup(dnsHost)
- .timeout(const Duration(seconds: 2)))
- .first;
- return dns.replaceFirst(dnsHost, dnsIp.address);
- } on Exception catch (_) {
- throw Exception('Failed to resolve DNS server address: $dns');
- }
- }
- return dns;
- }
- static Future<Dns> dns(String remoteDns, String directDns,
- String serverAddress, bool ipv4Only) async {
- remoteDns = await resolveDns(remoteDns);
- directDns = await resolveDns(directDns);
- if (directDns.contains('+local://')) {
- directDns = directDns.replaceFirst('+local', '');
- }
- List<DnsRule> dnsRules = [
- DnsRule(
- domain: ['geosite:cn'],
- server: 'local',
- ),
- ];
- if (!RegExp(ipRegExp).hasMatch(serverAddress) &&
- serverAddress != '127.0.0.1') {
- dnsRules.add(
- DnsRule(
- domain: [serverAddress],
- server: 'local',
- ),
- );
- }
- return Dns(
- servers: [
- DnsServer(
- tag: 'remote',
- address: remoteDns,
- detour: 'proxy',
- strategy: ipv4Only ? 'ipv4_only' : null,
- ),
- DnsServer(
- tag: 'local',
- address: directDns,
- detour: 'direct',
- strategy: ipv4Only ? 'ipv4_only' : null,
- ),
- ],
- rules: dnsRules,
- );
- }
- static Route route(List<xray_config.XrayRule> rules, bool configureDns) {
- List<RouteRule> routeRules = [];
- if (configureDns) {
- routeRules.add(
- RouteRule(
- protocol: 'dns',
- outbound: 'dns-out',
- ),
- );
- }
- routeRules.addAll(convertRules(rules));
- return Route(
- geoip: Geoip(path: p.join(binPath, 'geoip.db')),
- geosite: Geosite(path: p.join(binPath, 'geosite.db')),
- rules: routeRules,
- autoDetectInterface: true,
- finalTag: 'proxy',
- );
- }
- static List<RouteRule> convertRules(List<xray_config.XrayRule> xrayRules) {
- List<RouteRule> result = [];
- result.add(
- RouteRule(
- processName: SystemUtil.getCoreFileNames(),
- outbound: 'direct',
- ),
- );
- for (var xrayRule in xrayRules) {
- if (xrayRule.enabled) {
- List<String>? geosite;
- List<String>? domain;
- List<String>? geoip;
- List<String>? ipCidr;
- List<int>? port;
- List<String>? portRange;
- if (xrayRule.domain != null) {
- for (var domainItem in xrayRule.domain!) {
- if (domainItem.startsWith('geosite:')) {
- geosite ??= [];
- geosite.add(domainItem.replaceFirst('geosite:', ''));
- } else {
- domain ??= [];
- domain.add(domainItem);
- }
- }
- }
- if (xrayRule.ip != null) {
- for (var ipItem in xrayRule.ip!) {
- if (ipItem.startsWith('geoip:')) {
- geoip ??= [];
- geoip.add(ipItem.replaceFirst('geoip:', ''));
- } else {
- ipCidr ??= [];
- ipCidr.add(ipItem);
- }
- }
- }
- if (xrayRule.port != null) {
- List<String> tempPort = xrayRule.port!.split(',');
- for (var portItem in tempPort) {
- if (portItem.contains('-')) {
- portRange ??= [];
- portRange.add(portItem.replaceAll('-', ':'));
- } else {
- port ??= [];
- port.add(int.parse(portItem));
- }
- }
- }
- result.add(RouteRule(
- geosite: geosite,
- domain: domain,
- geoip: geoip,
- ipCidr: ipCidr,
- port: port,
- portRange: portRange,
- outbound: xrayRule.outboundTag,
- ));
- }
- }
- return result;
- }
- static Inbound mixedInbound(
- String listen, int listenPort, List<User>? users) {
- return Inbound(
- type: 'mixed',
- listen: listen,
- listenPort: listenPort,
- users: users,
- );
- }
- static Inbound tunInbound(String? inet4Address, String? inet6Address, int mtu,
- String stack, bool autoRoute, bool strictRoute, bool sniff) {
- return Inbound(
- type: 'tun',
- inet4Address: inet4Address,
- inet6Address: inet6Address,
- mtu: mtu,
- autoRoute: autoRoute,
- strictRoute: strictRoute,
- stack: stack,
- sniff: sniff,
- );
- }
- static Outbound generateOutbound(ServerBase server) {
- late Outbound outbound;
- switch (server.runtimeType) {
- case XrayServer:
- outbound = xrayOutbound(server as XrayServer);
- break;
- case ShadowsocksServer:
- outbound = shadowsocksOutbound(server as ShadowsocksServer);
- break;
- case TrojanServer:
- outbound = trojanOutbound(server as TrojanServer);
- break;
- case HysteriaServer:
- outbound = hysteriaOutbound(server as HysteriaServer);
- break;
- default:
- throw Exception(
- 'Sing-Box does not support this server type: ${server.protocol}');
- }
- return outbound;
- }
- static Outbound xrayOutbound(XrayServer server) {
- if (server.protocol == 'socks') {
- return socksOutbound(server);
- } else if (server.protocol == 'vmess' || server.protocol == 'vless') {
- return vProtocolOutbound(server);
- } else {
- throw Exception(
- 'Sing-Box does not support this server type: ${server.protocol}');
- }
- }
- static Outbound socksOutbound(XrayServer server) {
- return Outbound(
- type: 'socks',
- tag: 'proxy',
- server: server.address,
- serverPort: server.port,
- version: '5',
- );
- }
- static Outbound vProtocolOutbound(XrayServer server) {
- final utls = UTls(
- enabled: server.fingerPrint != null && server.fingerPrint != 'none',
- fingerprint: server.fingerPrint,
- );
- final reality = Reality(
- enabled: server.tls == 'reality',
- publicKey: server.publicKey ?? '',
- shortId: server.shortId,
- );
- final tls = Tls(
- enabled: server.tls == 'tls',
- serverName: server.serverName ?? server.address,
- insecure: server.allowInsecure,
- utls: utls,
- reality: reality,
- );
- final transport = Transport(
- type: server.transport,
- host: server.transport == 'httpupgrade'
- ? (server.host ?? server.address)
- : null,
- path: server.transport == 'ws' || server.transport == 'httpupgrade'
- ? (server.path ?? '/')
- : null,
- serviceName:
- server.transport == 'grpc' ? (server.serviceName ?? '/') : null,
- );
- return Outbound(
- type: server.protocol,
- tag: 'proxy',
- server: server.address,
- serverPort: server.port,
- uuid: server.uuid,
- flow: server.flow,
- alterId: server.protocol == 'vmess' ? server.alterId : null,
- security: server.protocol == 'vmess' ? server.encryption : null,
- tls: tls,
- transport: server.tls == 'reality' ? null : transport,
- );
- }
- static Outbound shadowsocksOutbound(ShadowsocksServer server) {
- return Outbound(
- type: 'shadowsocks',
- tag: 'proxy',
- server: server.address,
- serverPort: server.port,
- method: server.encryption,
- password: server.password,
- plugin: server.plugin,
- pluginOpts: server.plugin,
- );
- }
- static Outbound trojanOutbound(TrojanServer server) {
- final tls = Tls(
- enabled: true,
- serverName: server.serverName ?? server.address,
- insecure: server.allowInsecure,
- );
- return Outbound(
- type: 'trojan',
- tag: 'proxy',
- server: server.address,
- serverPort: server.port,
- password: server.password,
- network: 'tcp',
- tls: tls,
- );
- }
- static Outbound hysteriaOutbound(HysteriaServer server) {
- final tls = Tls(
- enabled: true,
- serverName: server.serverName ?? server.address,
- insecure: server.insecure,
- alpn: server.alpn?.split(','),
- );
- return Outbound(
- type: 'hysteria',
- tag: 'proxy',
- server: server.address,
- serverPort: server.port,
- upMbps: server.upMbps,
- downMbps: server.downMbps,
- obfs: server.obfs,
- auth: server.authType == 'none'
- ? (server.authType == 'base64' ? server.authPayload : null)
- : null,
- authStr: server.authType == 'none'
- ? (server.authType == 'str' ? server.authPayload : null)
- : null,
- recvWindowConn: server.recvWindowConn,
- recvWindow: server.recvWindow,
- tls: tls,
- );
- }
- }
|