diff --git a/README.md b/README.md
index 7b8e059..37e7b35 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
## 免费开源Http、Https抓包工具,支持Windows、Mac、Android、IOS, 全平台系统
+支持手机扫码连接,不用手动配置Wifi代理,包括配置同步。所有终端都可以互相扫码连接转发流量。
**Mac首次打开会提示已损坏,需要到系统偏好设置-安全性与隐私-允许任何来源。**
@@ -10,10 +11,8 @@
- [ ] 接下来会完善功能体验,JSON格式化展示,URL解码,UI优化。
- [ ] IOS上架app Store。
-- [ ] 后面桌面端和手机端整合,扫码连接啥的,不用手动配置Wifi代理,包括配置同步。
- [ ] 支持安卓微信小程序抓包,安卓分为系统证书和用户证书,下载的自签名根证书安装都是用户证书,微信不信任用户证书,不Root导致Https抓不了了, 目前市场上所有抓包软件抓不了微信的包,后面单独做个运行空间插件,动态反编译修改配置,信任用户证书来解决。
-
.
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 3b60783..64c55a5 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -45,17 +45,16 @@ android {
defaultConfig {
applicationId "com.network.proxy"
- // You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
- minSdkVersion 19
+ minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
+ multiDexEnabled true
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
- // TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 77172ea..7d94389 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -2,6 +2,7 @@
+
when (call.method) {
"startVpn" -> {
diff --git a/ios/Podfile b/ios/Podfile
index fdcc671..164df53 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/ProxyPin/PacketTunnelProvider.swift b/ios/ProxyPin/PacketTunnelProvider.swift
index 7fd3da7..9d5421a 100644
--- a/ios/ProxyPin/PacketTunnelProvider.swift
+++ b/ios/ProxyPin/PacketTunnelProvider.swift
@@ -18,7 +18,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
exit(EXIT_FAILURE)
}
let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1")
- networkSettings.mtu = 1500
NSLog(conf.debugDescription)
//http代理
let host = conf["proxyHost"] as! String
diff --git a/ios/ProxyPin/ProxyPin.entitlements b/ios/ProxyPin/ProxyPin.entitlements
index de73917..cea3252 100644
--- a/ios/ProxyPin/ProxyPin.entitlements
+++ b/ios/ProxyPin/ProxyPin.entitlements
@@ -14,9 +14,6 @@
allow-vpn
- com.apple.security.network.client
-
- com.apple.security.network.server
-
+
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index b5eed67..182555d 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 55;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 4702458..558abf2 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -61,5 +61,7 @@
UIViewControllerBasedStatusBarAppearance
+ NSCameraUsageDescription
+ 扫描二维码
diff --git a/ios/Runner/VpnManager.swift b/ios/Runner/VpnManager.swift
index c8ab2db..381c8a0 100755
--- a/ios/Runner/VpnManager.swift
+++ b/ios/Runner/VpnManager.swift
@@ -155,10 +155,11 @@ extension VpnManager{
}
}
- func disconnect(){
+ func disconnect() {
if (activeVPN != nil) {
print("stopVPNTunnel activeVPN")
activeVPN?.connection.stopVPNTunnel()
+ activeVPN = nil
return
}
diff --git a/lib/network/bin/server.dart b/lib/network/bin/server.dart
index 70776a0..3e8f2eb 100644
--- a/lib/network/bin/server.dart
+++ b/lib/network/bin/server.dart
@@ -27,7 +27,7 @@ class ProxyServer {
EventListener? listener;
RequestRewrites requestRewrites = RequestRewrites();
- List _initializedListeners = [];
+ final List _initializedListeners = [];
ProxyServer({this.listener});
diff --git a/lib/network/channel.dart b/lib/network/channel.dart
index 8e9b2a9..60f9272 100644
--- a/lib/network/channel.dart
+++ b/lib/network/channel.dart
@@ -42,9 +42,7 @@ class Channel {
final int remotePort;
Channel(this._socket)
- : _id = DateTime
- .now()
- .millisecondsSinceEpoch + Random().nextInt(999999),
+ : _id = DateTime.now().millisecondsSinceEpoch + Random().nextInt(999999),
remoteAddress = _socket.remoteAddress,
remotePort = _socket.remotePort;
@@ -56,6 +54,10 @@ class Channel {
set secureSocket(SecureSocket secureSocket) => _socket = secureSocket;
Future write(Object obj) async {
+ if (isClosed) {
+ return;
+ }
+
var data = pipeline._encoder.encode(obj);
_socket.add(data);
await _socket.flush();
@@ -115,9 +117,23 @@ class ChannelPipeline extends ChannelHandler {
_handler.channelActive(channel);
}
+ /// 转发请求
+ void relay(Channel clientChannel, Channel remoteChannel) {
+ var rawCodec = RawCodec();
+ clientChannel.pipeline.handle(rawCodec, rawCodec, RelayHandler(remoteChannel));
+ remoteChannel.pipeline.handle(rawCodec, rawCodec, RelayHandler(clientChannel));
+ }
+
@override
void channelRead(Channel channel, Uint8List msg) {
try {
+ HostAndPort? remote = channel.getAttribute(AttributeKeys.remote);
+ if (remote != null && channel.getAttribute(channel.id) != null) {
+ relay(channel, channel.getAttribute(channel.id));
+ _handler.channelRead(channel, msg);
+ return;
+ }
+
var data = _decoder.decode(msg);
if (data == null) {
return;
@@ -199,11 +215,11 @@ class HostAndPort {
@override
bool operator ==(Object other) =>
identical(this, other) ||
- other is HostAndPort &&
- runtimeType == other.runtimeType &&
- scheme == other.scheme &&
- host == other.host &&
- port == other.port;
+ other is HostAndPort &&
+ runtimeType == other.runtimeType &&
+ scheme == other.scheme &&
+ host == other.host &&
+ port == other.port;
@override
int get hashCode => scheme.hashCode ^ host.hashCode ^ port.hashCode;
@@ -250,6 +266,7 @@ abstract interface class ChannelInitializer {
class Network {
late Function _channelInitializer;
bool enableSsl = false;
+ String? remoteHost;
Network initChannel(void Function(Channel channel) initializer) {
_channelInitializer = initializer;
@@ -268,6 +285,11 @@ class Network {
_onEvent(Uint8List data, Channel channel) async {
HostAndPort? hostAndPort = channel.getAttribute(AttributeKeys.host);
+
+ if (remoteHost != null) {
+ channel.putAttribute(AttributeKeys.remote, HostAndPort.of(remoteHost!));
+ }
+
//黑名单 直接转发
if (HostFilter.filter(hostAndPort?.host) || (hostAndPort?.isSsl() == true && !enableSsl)) {
relay(channel, channel.getAttribute(channel.id));
@@ -288,8 +310,9 @@ class Network {
try {
//客户端ssl
Channel remoteChannel = channel.getAttribute(channel.id);
+
remoteChannel.secureSocket =
- await SecureSocket.secure(remoteChannel.socket, onBadCertificate: (certificate) => true);
+ await SecureSocket.secure(remoteChannel.socket, onBadCertificate: (certificate) => true);
remoteChannel.pipeline.listen(remoteChannel);
//服务端ssl
@@ -326,13 +349,14 @@ class Server extends Network {
Future stop() async {
if (!isRunning) return serverSocket;
isRunning = false;
- return serverSocket.close();
+ await serverSocket.close();
+ return serverSocket;
}
}
class Client extends Network {
Future connect(HostAndPort hostAndPort) async {
- return Socket.connect(hostAndPort.host, hostAndPort.port, timeout: const Duration(seconds: 5))
+ return Socket.connect(hostAndPort.host, hostAndPort.port, timeout: const Duration(seconds: 3))
.then((socket) => listen(socket));
}
}
diff --git a/lib/network/handler.dart b/lib/network/handler.dart
index 9293d59..f571e4d 100644
--- a/lib/network/handler.dart
+++ b/lib/network/handler.dart
@@ -1,3 +1,4 @@
+import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -5,7 +6,9 @@ import 'package:network_proxy/network/http/http.dart';
import 'package:network_proxy/network/http/http_headers.dart';
import 'package:network_proxy/network/util/attribute_keys.dart';
import 'package:network_proxy/network/util/file_read.dart';
+import 'package:network_proxy/network/util/host_filter.dart';
import 'package:network_proxy/network/util/request_rewrite.dart';
+import 'package:network_proxy/utils/ip.dart';
import 'channel.dart';
import 'http/codec.dart';
@@ -35,6 +38,33 @@ class HttpChannelHandler extends ChannelHandler {
@override
void channelRead(Channel channel, HttpRequest msg) async {
+ channel.putAttribute(AttributeKeys.request, msg);
+
+ if (msg.path == '/config' && (await localIp()) == msg.hostAndPort?.host) {
+ var response = HttpResponse(msg.protocolVersion, HttpStatus.ok);
+ var body = {
+ "requestRewrites": requestRewrites?.toJson(),
+ 'whitelist': HostFilter.whitelist.toJson(),
+ 'blacklist': HostFilter.blacklist.toJson(),
+ };
+ response.body = utf8.encode(json.encode(body));
+ channel.writeAndClose(response);
+ return;
+ }
+ if ((await localIp()) == msg.hostAndPort?.host) {
+ var response = HttpResponse(msg.protocolVersion, HttpStatus.ok);
+ response.body = utf8.encode('pong');
+ response.headers.set("os", Platform.operatingSystem);
+ response.headers.set("hostname", Platform.isAndroid ? Platform.operatingSystem : Platform.localHostname);
+ channel.writeAndClose(response);
+ return;
+ }
+
+ if (msg.uri == 'http://proxy.pin/ssl' || msg.requestUrl == 'http://127.0.0.1:${channel.socket.port}/ssl') {
+ _crtDownload(channel, msg);
+ return;
+ }
+
forward(channel, msg).catchError((error, trace) {
channel.close();
if (error is SocketException &&
@@ -54,19 +84,11 @@ class HttpChannelHandler extends ChannelHandler {
/// 转发请求
Future forward(Channel channel, HttpRequest httpRequest) async {
- channel.putAttribute(AttributeKeys.request, httpRequest);
-
- if (httpRequest.uri == 'http://proxy.pin/ssl' ||
- httpRequest.requestUrl == 'http://127.0.0.1:${channel.socket.port}/ssl') {
- _crtDownload(channel, httpRequest);
- return;
- }
-
var remoteChannel = await _getRemoteChannel(channel, httpRequest);
//实现抓包代理转发
if (httpRequest.method != HttpMethod.connect) {
- // log.i("[${channel.id}] ${httpRequest.requestUrl}");
+ log.i("[${channel.id}] ${httpRequest.requestUrl}");
var replaceBody = requestRewrites?.findRequestReplaceWith(httpRequest.path);
if (replaceBody?.isNotEmpty == true) {
@@ -110,6 +132,15 @@ class HttpChannelHandler extends ChannelHandler {
clientChannel.putAttribute(AttributeKeys.host, hostAndPort);
var proxyHandler = HttpResponseProxyHandler(clientChannel, listener: listener, requestRewrites: requestRewrites);
+
+ HostAndPort? remote = clientChannel.getAttribute(AttributeKeys.remote);
+ if (remote != null) {
+ var proxyChannel = await HttpClients.connect(remote, proxyHandler);
+ clientChannel.putAttribute(clientId, proxyChannel);
+ proxyChannel.write(httpRequest);
+ return proxyChannel;
+ }
+
var proxyChannel = await HttpClients.connect(hostAndPort, proxyHandler);
clientChannel.putAttribute(clientId, proxyChannel);
@@ -134,7 +165,7 @@ class HttpResponseProxyHandler extends ChannelHandler {
@override
void channelRead(Channel channel, HttpResponse msg) {
msg.request = clientChannel.getAttribute(AttributeKeys.request);
- msg.request?.response= msg;
+ msg.request?.response = msg;
// log.i("[${clientChannel.id}] Response ${msg.bodyAsString}");
var replaceBody = requestRewrites?.findResponseReplaceWith(msg.request?.path);
@@ -172,10 +203,39 @@ class RelayHandler extends ChannelHandler