system_proxy.dart 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import 'dart:io';
  2. import 'package:naiyouwl/app/utils/logger.dart';
  3. class SystemProxyServer {
  4. String server;
  5. String get host {
  6. return server.split(':')[0];
  7. }
  8. String get port {
  9. return server.split(':')[1];
  10. }
  11. SystemProxyServer(this.server);
  12. }
  13. class SystemProxyConfig {
  14. String? http;
  15. String? https;
  16. String? socks;
  17. SystemProxyConfig({this.http, this.https, this.socks});
  18. }
  19. class SystemProxyPlatform {
  20. Future<void> set(SystemProxyConfig conf) async {
  21. throw UnimplementedError();
  22. }
  23. Future<SystemProxyConfig> get() async {
  24. throw UnimplementedError();
  25. }
  26. }
  27. class MacSystemProxy extends SystemProxyPlatform {
  28. static MacSystemProxy instance = MacSystemProxy();
  29. Future<List<String>> getNetworks() async {
  30. final result = await Process.run('networksetup', ['-listallnetworkservices']);
  31. return result.stdout.toString().trim().split('\n').sublist(1);
  32. }
  33. @override
  34. Future<void> set(SystemProxyConfig conf) async {
  35. final networks = await getNetworks();
  36. List<String> commands = [];
  37. for (var network in networks) {
  38. if (conf.http != null) {
  39. final http = SystemProxyServer(conf.http!);
  40. commands.add('networksetup -setwebproxy "$network" "${http.host}" "${http.port}"');
  41. } else {
  42. commands.add('networksetup -setwebproxy "$network" "" ""');
  43. commands.add('networksetup -setwebproxystate "$network" off');
  44. }
  45. if (conf.https != null) {
  46. final https = SystemProxyServer(conf.https!);
  47. commands.add('networksetup -setsecurewebproxy "$network" "${https.host}" "${https.port}"');
  48. } else {
  49. commands.add('networksetup -setsecurewebproxy "$network" "" ""');
  50. commands.add('networksetup -setsecurewebproxystate "$network" off');
  51. }
  52. if (conf.socks != null) {
  53. final socks = SystemProxyServer(conf.socks!);
  54. commands.add('networksetup -setsocksfirewallproxy "$network" "${socks.host}" "${socks.port}"');
  55. } else {
  56. commands.add('networksetup -setsocksfirewallproxy "$network" "" ""');
  57. commands.add('networksetup -setsocksfirewallproxystate "$network" off');
  58. }
  59. }
  60. log.debug('MacSystemProxy.set:', commands);
  61. await Process.run('bash', ['-c', commands.join(' && ')]);
  62. }
  63. @override
  64. Future<SystemProxyConfig> get() async {
  65. final out = (await Process.run('scutil', ['--proxy'])).stdout.toString().trim();
  66. final states = ['HTTP', 'HTTPS', 'SOCKS'].map((it) {
  67. final enableReg = RegExp('(?<=${it}Enable\\s*:\\s*)([^\\s]+)').firstMatch(out);
  68. final hostReg = RegExp('(?<=${it}Proxy\\s*:\\s*)([^\\s]+)').firstMatch(out);
  69. final portReg = RegExp('(?<=${it}Port\\s*:\\s*)([^\\s]+)').firstMatch(out);
  70. final enable = enableReg?.group(1);
  71. final host = hostReg?.group(1);
  72. final port = portReg?.group(1);
  73. if (enable == null || enable == '0' || host == null || port == null) return null;
  74. return '$host:$port';
  75. }).toList();
  76. return SystemProxyConfig(http: states[0], https: states[1], socks: states[2]);
  77. }
  78. }
  79. class WinSystemProxy extends SystemProxyPlatform {
  80. static String regPath = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings';
  81. static WinSystemProxy instance = WinSystemProxy();
  82. @override
  83. Future<void> set(SystemProxyConfig conf) async {
  84. // socks 会丢失域名信息 导致规则失效
  85. // http=127.0.0.1:7893;https=127.0.0.1:7890;socks=127.0.0.1:7891; chrome, firefox use https
  86. // http://127.0.0.1:7893;https=127.0.0.1:7890;socks=127.0.0.1:7891; chrome use http; firefox use https
  87. // http://127.0.0.1:7893;https=127.0.0.1:7890; chrome use http; firefox use https
  88. // https=127.0.0.1:7890;socks=127.0.0.1:7891; chrome, firefox use https
  89. // http://127.0.0.1:7893;socks=127.0.0.1:7891; chrome, firefox use http
  90. // http=127.0.0.1:7893;socks=127.0.0.1:7891; chrome use socks, firefox not use
  91. // socks=127.0.0.1:7891; chrome, firefox use socks4
  92. // http=127.0.0.1:7893; chrome, firefox not use
  93. // http=xxx 不建议使用
  94. String servers = "";
  95. String loa = '127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*';
  96. if (conf.http != null) servers += "${conf.http}";
  97. // if (conf.https != null) servers += "https=${conf.https};";
  98. // if (conf.socks != null) servers += "socks=${conf.socks};";
  99. if (servers.isNotEmpty) {
  100. await Process.run('reg', ['add', regPath, '/v', 'ProxyEnable', '/t', 'REG_DWORD', '/d', '1', '/f']);
  101. await Process.run('reg', ['add', regPath, '/v', 'ProxyServer', '/t', 'REG_SZ', '/d', servers, '/f']);
  102. await Process.run('reg', ['add', regPath, '/v', 'ProxyOverride', '/t', 'REG_SZ', '/d', loa, '/f']);
  103. } else {
  104. await Process.run('reg', ['add', regPath, '/v', 'ProxyEnable', '/t', 'REG_DWORD', '/d', '0', '/f']);
  105. await Process.run('reg', ['add', regPath, '/v', 'ProxyServer', '/t', 'REG_SZ', '/d', '', '/f']);
  106. await Process.run('reg', ['add', regPath, '/v', 'ProxyOverride', '/t', 'REG_SZ', '/d', '', '/f']);
  107. }
  108. }
  109. @override
  110. Future<SystemProxyConfig> get() async {
  111. final enable = (await Process.run('reg', ['query', regPath, '/v', 'ProxyEnable'])).stdout.toString().contains('0x1');
  112. final result = SystemProxyConfig();
  113. if (!enable) return result;
  114. final out = await Process.run('reg', ['query', regPath, '/v', 'ProxyServer']);
  115. final outStr = out.stdout.toString().trim();
  116. final serversStr = RegExp(r'(?<=ProxyServer\s+REG_SZ\s+)(?!\s+).+').firstMatch(outStr)?.group(0);
  117. if (serversStr != null) {
  118. final serverReg = RegExp(r"((?:https?)|(?:socks))(?:(?:\:\/\/)|(?:=))(\d+\.\d+\.\d+\.\d+\:\d+)");
  119. final results = serversStr.split(";").where((it) => it.isNotEmpty).map((it) => serverReg.firstMatch(it)?.groups([1, 2])).whereType<List>();
  120. for (var it in results) {
  121. final state = it[1];
  122. switch (it[0]) {
  123. case 'http':
  124. result.http = state;
  125. break;
  126. case 'https':
  127. result.https = state;
  128. break;
  129. case 'socks':
  130. result.socks = state;
  131. break;
  132. }
  133. }
  134. }
  135. return result;
  136. }
  137. }
  138. class SystemProxy extends SystemProxyPlatform {
  139. static SystemProxy instance = SystemProxy();
  140. @override
  141. Future<void> set(SystemProxyConfig conf) async {
  142. try {
  143. log.time('setProxy');
  144. if (Platform.isWindows) {
  145. return WinSystemProxy.instance.set(conf);
  146. } else if (Platform.isMacOS) {
  147. return MacSystemProxy.instance.set(conf);
  148. } else {
  149. throw UnimplementedError();
  150. }
  151. } catch (e) {
  152. rethrow;
  153. } finally {
  154. log.timeEnd('setProxy');
  155. }
  156. }
  157. @override
  158. Future<SystemProxyConfig> get() async {
  159. try {
  160. log.time('getProxyState');
  161. if (Platform.isWindows) {
  162. return WinSystemProxy.instance.get();
  163. } else if (Platform.isMacOS) {
  164. return MacSystemProxy.instance.get();
  165. } else {
  166. throw UnimplementedError();
  167. }
  168. } finally {
  169. log.timeEnd('getProxyState');
  170. }
  171. }
  172. }