clash_config.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. class ClashConfig {
  2. final String logLevel;
  3. final bool? ipv6;
  4. final bool? allowLan;
  5. final String? bindAddress;
  6. final String mode;
  7. final int mixedPort;
  8. final String? externalController;
  9. final bool? unifiedDelay;
  10. final bool? geodataMode;
  11. final bool? tcpConcurrent;
  12. final String? findProcessMode;
  13. final String? globalClientFingerprint;
  14. final Map<String, bool>? profile;
  15. final Sniffer? sniffer;
  16. final DNS? dns;
  17. final Tun? tun;
  18. final List<Map<String, dynamic>>? proxies;
  19. final List<ProxyGroup>? proxyGroups;
  20. final List<String>? rules;
  21. ClashConfig({
  22. required this.logLevel,
  23. this.ipv6,
  24. this.allowLan,
  25. this.bindAddress,
  26. required this.mode,
  27. required this.mixedPort,
  28. this.externalController,
  29. this.unifiedDelay,
  30. this.geodataMode,
  31. this.tcpConcurrent,
  32. this.findProcessMode,
  33. this.globalClientFingerprint,
  34. this.profile,
  35. this.sniffer,
  36. this.dns,
  37. this.tun,
  38. this.proxies,
  39. this.proxyGroups,
  40. this.rules,
  41. });
  42. factory ClashConfig.fromJson(Map<String, dynamic> json) {
  43. return ClashConfig(
  44. logLevel: json['log-level'],
  45. ipv6: json['ipv6'],
  46. allowLan: json['allow-lan'],
  47. bindAddress: json['bind-address'],
  48. mode: json['mode'],
  49. mixedPort: json['mixed-port'],
  50. externalController: json['external-controller'],
  51. unifiedDelay: json['unified-delay'],
  52. geodataMode: json['geodata-mode'],
  53. tcpConcurrent: json['tcp-concurrent'],
  54. findProcessMode: json['find-process-mode'],
  55. globalClientFingerprint: json['global-client-fingerprint'],
  56. profile: json['profile'] != null ? Map<String, bool>.from(json['profile']) : null,
  57. sniffer: json['sniffer'] != null ? Sniffer.fromJson(json['sniffer']) : null,
  58. dns: DNS.fromJson(json['dns']),
  59. tun: json['tun'] != null ? Tun.fromJson(json['tun']) : null,
  60. proxies: List<Map<String, dynamic>>.from(json['proxies']),
  61. proxyGroups: (json['proxy-groups'] as List)
  62. .map((e) => ProxyGroup.fromJson(e))
  63. .toList(),
  64. rules: List<String>.from(json['rules']),
  65. );
  66. }
  67. Map<String, dynamic> toJson() {
  68. return {
  69. 'log-level': logLevel,
  70. if (ipv6 != null) 'ipv6': ipv6,
  71. if (allowLan != null) 'allow-lan': allowLan,
  72. if (bindAddress != null) 'bind-address': bindAddress,
  73. 'mode': mode,
  74. 'mixed-port': mixedPort,
  75. if (externalController != null) 'external-controller': externalController,
  76. if (unifiedDelay != null) 'unified-delay': unifiedDelay,
  77. if (geodataMode != null) 'geodata-mode': geodataMode,
  78. if (tcpConcurrent != null) 'tcp-concurrent': tcpConcurrent,
  79. if (findProcessMode != null) 'find-process-mode': findProcessMode,
  80. if (globalClientFingerprint != null) 'global-client-fingerprint': globalClientFingerprint,
  81. if (profile != null) 'profile': profile,
  82. if (sniffer != null) 'sniffer': sniffer!.toJson(),
  83. if (dns != null) 'dns': dns?.toJson(),
  84. if (tun != null) 'tun': tun!.toJson(),
  85. if (proxies != null) 'proxies': proxies,
  86. if (proxyGroups != null)'proxy-groups': proxyGroups?.map((e) => e.toJson()).toList(),
  87. 'rules': rules,
  88. };
  89. }
  90. }
  91. class BaseProxy {
  92. final String name;
  93. final String server;
  94. final int port;
  95. final bool? udp;
  96. BaseProxy({
  97. required this.name,
  98. required this.server,
  99. required this.port,
  100. this.udp,
  101. });
  102. Map<String, dynamic> toJson() {
  103. return {
  104. 'name': name,
  105. 'server': server,
  106. 'port': port,
  107. if (udp != null) 'udp': udp,
  108. };
  109. }
  110. }
  111. class SSProxy extends BaseProxy {
  112. final String type;
  113. final String password;
  114. final String cipher;
  115. final String? plugin;
  116. final Map<String, dynamic>? pluginOpts;
  117. SSProxy({
  118. required String name,
  119. required String server,
  120. required int port,
  121. bool? udp,
  122. required this.type,
  123. required this.password,
  124. required this.cipher,
  125. this.plugin,
  126. this.pluginOpts,
  127. }) : super(name: name, server: server, port: port, udp: udp);
  128. factory SSProxy.fromJson(Map<String, dynamic> json) {
  129. return SSProxy(
  130. name: json['name'],
  131. server: json['server'],
  132. port: json['port'],
  133. udp: json['udp'],
  134. type: json['type'],
  135. password: json['password'],
  136. cipher: json['cipher'],
  137. plugin: json['plugin'],
  138. pluginOpts: json['plugin-opts'],
  139. );
  140. }
  141. Map<String, dynamic> toJson() {
  142. return {
  143. 'name': name,
  144. 'type': type,
  145. 'server': server,
  146. 'port': port,
  147. 'password': password,
  148. 'cipher': cipher,
  149. if (udp != null) 'udp': udp,
  150. if (plugin != null) 'plugin': plugin,
  151. if (pluginOpts != null) 'plugin-opts': pluginOpts,
  152. };
  153. }
  154. }
  155. class VlessProxy extends BaseProxy {
  156. final String uuid;
  157. final String? flow;
  158. final bool tls;
  159. final String? servername;
  160. final String network;
  161. final Map<String, dynamic>? smux;
  162. final List<String>? alpn;
  163. final String? fingerprint;
  164. final String? clientFingerprint;
  165. final bool? skipCertVerify;
  166. final Map<String, dynamic>? realityOpts;
  167. VlessProxy({
  168. required String name,
  169. required String server,
  170. required int port,
  171. bool? udp,
  172. required this.uuid,
  173. this.flow,
  174. required this.tls,
  175. this.servername,
  176. required this.network,
  177. this.smux,
  178. this.alpn,
  179. this.fingerprint,
  180. this.clientFingerprint,
  181. this.skipCertVerify,
  182. this.realityOpts,
  183. }) : super(name: name, server: server, port: port, udp: udp);
  184. factory VlessProxy.fromJson(Map<String, dynamic> json) {
  185. return VlessProxy(
  186. name: json['name'],
  187. server: json['server'],
  188. port: json['port'],
  189. udp: json['udp'] ?? false,
  190. uuid: json['uuid'],
  191. flow: json['flow'],
  192. tls: json['tls'],
  193. servername: json['servername'],
  194. network: json['network'],
  195. smux: json['smux'],
  196. alpn: json['alpn']?.cast<String>(),
  197. fingerprint: json['fingerprint'],
  198. clientFingerprint: json['client-fingerprint'],
  199. skipCertVerify: json['skip-cert-verify'],
  200. realityOpts: json['reality-opts'],
  201. );
  202. }
  203. Map<String, dynamic> toJson() {
  204. return {
  205. 'name': name,
  206. 'type': 'vless',
  207. 'server': server,
  208. 'port': port,
  209. 'udp': udp,
  210. 'uuid': uuid,
  211. if (flow != null) 'flow': flow,
  212. 'tls': tls,
  213. if (servername != null) 'servername': servername,
  214. 'network': network,
  215. if (smux != null) 'smux': smux,
  216. if (alpn != null) 'alpn': alpn,
  217. if (fingerprint != null) 'fingerprint': fingerprint,
  218. if (clientFingerprint != null) 'client-fingerprint': clientFingerprint,
  219. if (skipCertVerify != null) 'skip-cert-verify': skipCertVerify,
  220. if (realityOpts != null) 'reality-opts': realityOpts,
  221. };
  222. }
  223. }
  224. class VmessProxy extends BaseProxy {
  225. final String uuid;
  226. final int? alterId;
  227. final String? cipher;
  228. final String? network;
  229. final Map<String, dynamic>? wsOpts;
  230. final String? servername;
  231. final bool? skipCertVerify;
  232. final List<String>? alpn;
  233. VmessProxy({
  234. required String name,
  235. required String server,
  236. required int port,
  237. bool? udp,
  238. required this.uuid,
  239. this.alterId,
  240. this.cipher,
  241. this.network = 'tcp',
  242. this.wsOpts,
  243. this.servername,
  244. this.skipCertVerify,
  245. this.alpn,
  246. }) : super(name: name, server: server, port: port, udp: udp);
  247. factory VmessProxy.fromJson(Map<String, dynamic> json) {
  248. return VmessProxy(
  249. name: json['name'],
  250. server: json['server'],
  251. port: json['port'],
  252. udp: json['udp'],
  253. uuid: json['uuid'],
  254. alterId: json['alterId'],
  255. cipher: json['cipher'],
  256. network: json['network'] ?? 'tcp',
  257. wsOpts: json['ws-opts'],
  258. servername: json['servername'],
  259. skipCertVerify: json['skip-cert-verify'],
  260. alpn: json['alpn']?.cast<String>(),
  261. );
  262. }
  263. Map<String, dynamic> toJson() {
  264. return {
  265. 'name': name,
  266. 'type': 'vmess',
  267. 'server': server,
  268. 'port': port,
  269. 'uuid': uuid,
  270. 'udp': udp,
  271. if (alterId != null) 'alterId': alterId,
  272. if (cipher != null) 'cipher': cipher,
  273. 'network': network,
  274. if (wsOpts != null) 'ws-opts': wsOpts,
  275. if (servername != null) 'servername': servername,
  276. if (skipCertVerify != null) 'skip-cert-verify': skipCertVerify,
  277. if (alpn != null) 'alpn': alpn,
  278. };
  279. }
  280. }
  281. class TrojanProxy extends BaseProxy {
  282. final String password;
  283. final String? sni;
  284. final String? network;
  285. final String? clientFingerprint;
  286. final String? fingerprint;
  287. final bool? skipCertVerify;
  288. TrojanProxy({
  289. required String name,
  290. required String server,
  291. required int port,
  292. bool? udp,
  293. required this.password,
  294. this.sni,
  295. this.network,
  296. this.clientFingerprint,
  297. this.fingerprint,
  298. this.skipCertVerify,
  299. }) : super(name: name, server: server, port: port, udp: udp);
  300. factory TrojanProxy.fromJson(Map<String, dynamic> json) {
  301. return TrojanProxy(
  302. name: json['name'],
  303. server: json['server'],
  304. port: json['port'],
  305. udp: json['udp'],
  306. password: json['password'],
  307. sni: json['sni'],
  308. network: json['network'],
  309. clientFingerprint: json['client-fingerprint'],
  310. fingerprint: json['fingerprint'],
  311. skipCertVerify: json['skip-cert-verify'],
  312. );
  313. }
  314. Map<String, dynamic> toJson() {
  315. return {
  316. 'name': name,
  317. 'type': 'trojan',
  318. 'server': server,
  319. 'port': port,
  320. 'password': password,
  321. 'udp': udp,
  322. if (sni != null) 'sni': sni,
  323. if (network != null) 'network': network,
  324. if (clientFingerprint != null) 'client-fingerprint': clientFingerprint,
  325. if (fingerprint != null) 'fingerprint': fingerprint,
  326. if (skipCertVerify != null) 'skip-cert-verify': skipCertVerify,
  327. };
  328. }
  329. }
  330. class ProxyGroup {
  331. final String name;
  332. final String type;
  333. final List<String> proxies;
  334. ProxyGroup({
  335. required this.name,
  336. required this.type,
  337. required this.proxies,
  338. });
  339. factory ProxyGroup.fromJson(Map<String, dynamic> json) {
  340. return ProxyGroup(
  341. name: json['name'],
  342. type: json['type'],
  343. proxies: List<String>.from(json['proxies']),
  344. );
  345. }
  346. Map<String, dynamic> toJson() {
  347. return {
  348. 'name': name,
  349. 'type': type,
  350. 'proxies': proxies,
  351. };
  352. }
  353. }
  354. class DNS {
  355. final bool enable;
  356. final String listen;
  357. final bool ipv6;
  358. final String enhancedMode;
  359. final List<String>? fakeIpFilter;
  360. final List<String> nameserver;
  361. final List<String> proxyServerNameserver;
  362. final Map<String, List<String>> nameserverPolicy;
  363. DNS({
  364. required this.enable,
  365. required this.listen,
  366. required this.ipv6,
  367. required this.enhancedMode,
  368. this.fakeIpFilter,
  369. required this.nameserver,
  370. required this.proxyServerNameserver,
  371. required this.nameserverPolicy,
  372. });
  373. factory DNS.fromJson(Map<String, dynamic> json) {
  374. return DNS(
  375. enable: json['enable'],
  376. listen: json['listen'],
  377. ipv6: json['ipv6'],
  378. enhancedMode: json['enhanced-mode'],
  379. fakeIpFilter: json['fake-ip-filter'] != null ? List<String>.from(json['fake-ip-filter']) : null,
  380. nameserver: List<String>.from(json['nameserver']),
  381. proxyServerNameserver: List<String>.from(json['proxy-server-nameserver']),
  382. nameserverPolicy: Map<String, List<String>>.from(json['nameserver-policy'].map(
  383. (key, value) => MapEntry(key, List<String>.from(value)),
  384. )),
  385. );
  386. }
  387. Map<String, dynamic> toJson() {
  388. final Map<String, dynamic> data = {
  389. 'enable': enable,
  390. 'listen': listen,
  391. 'ipv6': ipv6,
  392. 'enhanced-mode': enhancedMode,
  393. 'nameserver': nameserver,
  394. 'proxy-server-nameserver': proxyServerNameserver,
  395. 'nameserver-policy': nameserverPolicy,
  396. };
  397. if (fakeIpFilter != null) {
  398. data['fake-ip-filter'] = fakeIpFilter;
  399. }
  400. return data;
  401. }
  402. }
  403. class Sniffer {
  404. final bool enable;
  405. final Map<String, Map<String, dynamic>> sniff;
  406. final List<String> skipDomain;
  407. Sniffer({
  408. required this.enable,
  409. required this.sniff,
  410. required this.skipDomain,
  411. });
  412. factory Sniffer.fromJson(Map<String, dynamic> json) {
  413. return Sniffer(
  414. enable: json['enable'],
  415. sniff: Map<String, Map<String, dynamic>>.from(json['sniff']),
  416. skipDomain: List<String>.from(json['skip-domain']),
  417. );
  418. }
  419. Map<String, dynamic> toJson() {
  420. return {
  421. 'enable': enable,
  422. 'sniff': sniff,
  423. 'skip-domain': skipDomain,
  424. };
  425. }
  426. }
  427. class Tun {
  428. final bool enable;
  429. final String stack;
  430. final bool autoRoute;
  431. final bool autoRedirect;
  432. final bool autoDetectInterface;
  433. final List<String> dnsHijack;
  434. Tun({
  435. required this.enable,
  436. required this.stack,
  437. required this.autoRoute,
  438. required this.autoRedirect,
  439. required this.autoDetectInterface,
  440. required this.dnsHijack,
  441. });
  442. factory Tun.fromJson(Map<String, dynamic> json) {
  443. return Tun(
  444. enable: json['enable'],
  445. stack: json['stack'],
  446. autoRoute: json['auto-route'],
  447. autoRedirect: json['auto-redirect'],
  448. autoDetectInterface: json['auto-detect-interface'],
  449. dnsHijack: List<String>.from(json['dns-hijack']),
  450. );
  451. }
  452. Map<String, dynamic> toJson() {
  453. return {
  454. 'enable': enable,
  455. 'stack': stack,
  456. 'auto-route': autoRoute,
  457. 'auto-redirect': autoRedirect,
  458. 'auto-detect-interface': autoDetectInterface,
  459. 'dns-hijack': dnsHijack,
  460. };
  461. }
  462. }
  463. // 示例用法
  464. final sniffer = Sniffer(
  465. enable: true,
  466. sniff: {
  467. 'HTTP': {
  468. 'ports': [80, '8080-8880'],
  469. 'override-destination': true,
  470. },
  471. 'TLS': {
  472. 'ports': [443, 8443],
  473. },
  474. 'QUIC': {
  475. 'ports': [443, 8443],
  476. },
  477. },
  478. skipDomain: ['Mijia Cloud'],
  479. );