mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-10 00:44:12 +08:00
建立连接异常显示请求体
This commit is contained in:
@@ -31,17 +31,20 @@ import 'handler.dart';
|
||||
abstract class ChannelHandler<T> {
|
||||
var log = logger;
|
||||
|
||||
///连接建立
|
||||
void channelActive(Channel channel) {}
|
||||
|
||||
///读取数据事件
|
||||
void channelRead(Channel channel, T msg) {}
|
||||
|
||||
///连接断开
|
||||
void channelInactive(Channel channel) {
|
||||
// log.i("close $channel");
|
||||
}
|
||||
|
||||
void exceptionCaught(Channel channel, dynamic error, {StackTrace? trace}) {
|
||||
HostAndPort? attribute = channel.getAttribute(AttributeKeys.host);
|
||||
log.e("error $attribute $channel", error: error, stackTrace: trace);
|
||||
log.e("[${channel.id}] error $attribute $channel", error: error, stackTrace: trace);
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
@@ -63,6 +66,8 @@ class Channel {
|
||||
//是否写入中
|
||||
bool isWriting = false;
|
||||
|
||||
Object? error; //异常
|
||||
|
||||
Channel(this._socket)
|
||||
: _id = DateTime.now().millisecondsSinceEpoch + Random().nextInt(999999),
|
||||
remoteAddress = _socket.remoteAddress,
|
||||
@@ -80,7 +85,7 @@ class Channel {
|
||||
|
||||
Future<void> write(Object obj) async {
|
||||
if (isClosed) {
|
||||
logger.w("channel is closed $obj");
|
||||
logger.w("[$id] channel is closed $obj");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -154,6 +159,7 @@ class ChannelPipeline extends ChannelHandler<Uint8List> {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/// 监听
|
||||
void listen(Channel channel) {
|
||||
buffer.clear();
|
||||
|
||||
@@ -174,10 +180,10 @@ class ChannelPipeline extends ChannelHandler<Uint8List> {
|
||||
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));
|
||||
|
||||
@@ -69,29 +69,14 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
@override
|
||||
void exceptionCaught(Channel channel, error, {StackTrace? trace}) {
|
||||
super.exceptionCaught(channel, error, trace: trace);
|
||||
HostAndPort? hostAndPort = channel.getAttribute(AttributeKeys.host);
|
||||
hostAndPort ??= HostAndPort.host(channel.remoteAddress.host, channel.remotePort);
|
||||
String message = error.toString();
|
||||
HttpStatus status = HttpStatus(-1, message);
|
||||
if (error is HandshakeException) {
|
||||
status = HttpStatus(-2, 'SSL握手失败');
|
||||
} else if (error is ParserException) {
|
||||
status = HttpStatus(-3, error.message);
|
||||
} else if (error is SocketException) {
|
||||
status = HttpStatus(-4, error.message);
|
||||
}
|
||||
HttpRequest request = HttpRequest(HttpMethod.connect, hostAndPort.domain)
|
||||
..body = message.codeUnits
|
||||
..hostAndPort = hostAndPort;
|
||||
request.response = HttpResponse(status)..body = message.codeUnits;
|
||||
listener?.onRequest(channel, request);
|
||||
listener?.onResponse(channel, request.response!);
|
||||
_exceptionHandler(channel, channel.getAttribute(AttributeKeys.request), error);
|
||||
}
|
||||
|
||||
@override
|
||||
void channelInactive(Channel channel) {
|
||||
Channel? remoteChannel = channel.getAttribute(channel.id);
|
||||
remoteChannel?.close();
|
||||
// log.i("[${channel.id}] close ${channel.error}");
|
||||
}
|
||||
|
||||
//请求本服务
|
||||
@@ -118,11 +103,27 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
|
||||
/// 转发请求
|
||||
Future<void> forward(Channel channel, HttpRequest httpRequest) async {
|
||||
// log.i("[${channel.id}] ${httpRequest.method.name} ${httpRequest.requestUrl}");
|
||||
log.i("[${channel.id}] ${httpRequest.method.name} ${httpRequest.requestUrl}");
|
||||
if (channel.error != null) {
|
||||
_exceptionHandler(channel, httpRequest, channel.error);
|
||||
return;
|
||||
}
|
||||
|
||||
//获取远程连接
|
||||
var remoteChannel = await _getRemoteChannel(channel, httpRequest);
|
||||
remoteChannel.putAttribute(remoteChannel.id, channel);
|
||||
Channel remoteChannel;
|
||||
try {
|
||||
remoteChannel = await _getRemoteChannel(channel, httpRequest);
|
||||
remoteChannel.putAttribute(remoteChannel.id, channel);
|
||||
} catch (error) {
|
||||
|
||||
channel.error = error; //记录异常
|
||||
//https代理新建连接请求
|
||||
if (httpRequest.method == HttpMethod.connect) {
|
||||
await channel.write(
|
||||
HttpResponse(HttpStatus.ok.reason('Connection established'), protocolVersion: httpRequest.protocolVersion));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//实现抓包代理转发
|
||||
if (httpRequest.method != HttpMethod.connect) {
|
||||
@@ -140,6 +141,7 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 下载证书
|
||||
void _crtDownload(Channel channel, HttpRequest request) async {
|
||||
const String fileMimeType = 'application/x-x509-ca-cert';
|
||||
var response = HttpResponse(HttpStatus.ok);
|
||||
@@ -192,9 +194,30 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
|
||||
await clientChannel.write(
|
||||
HttpResponse(HttpStatus.ok.reason('Connection established'), protocolVersion: httpRequest.protocolVersion));
|
||||
}
|
||||
|
||||
return proxyChannel;
|
||||
}
|
||||
|
||||
/// 异常处理
|
||||
_exceptionHandler(Channel channel, HttpRequest? request, error) {
|
||||
HostAndPort? hostAndPort = channel.getAttribute(AttributeKeys.host);
|
||||
hostAndPort ??= HostAndPort.host(channel.remoteAddress.host, channel.remotePort);
|
||||
String message = error.toString();
|
||||
HttpStatus status = HttpStatus(-1, message);
|
||||
if (error is HandshakeException) {
|
||||
status = HttpStatus(-2, 'SSL握手失败');
|
||||
} else if (error is ParserException) {
|
||||
status = HttpStatus(-3, error.message);
|
||||
} else if (error is SocketException) {
|
||||
status = HttpStatus(-4, error.message);
|
||||
}
|
||||
request ??= HttpRequest(HttpMethod.connect, hostAndPort.domain)
|
||||
..body = message.codeUnits
|
||||
..hostAndPort = hostAndPort;
|
||||
|
||||
request.response = HttpResponse(status)..body = message.codeUnits;
|
||||
listener?.onRequest(channel, request);
|
||||
listener?.onResponse(channel, request.response!);
|
||||
}
|
||||
}
|
||||
|
||||
/// http响应代理
|
||||
|
||||
@@ -48,11 +48,12 @@ class Network {
|
||||
}
|
||||
|
||||
_onEvent(Uint8List data, Channel channel) async {
|
||||
//手机扫码转发远程地址
|
||||
if (configuration?.remoteHost != null) {
|
||||
channel.putAttribute(AttributeKeys.remote, HostAndPort.of(configuration!.remoteHost!));
|
||||
}
|
||||
|
||||
//代理信息
|
||||
//外部代理信息
|
||||
if (configuration?.externalProxy?.enabled == true) {
|
||||
channel.putAttribute(AttributeKeys.proxyInfo, configuration!.externalProxy!);
|
||||
}
|
||||
@@ -79,12 +80,14 @@ class Network {
|
||||
channel.pipeline.channelRead(channel, data);
|
||||
}
|
||||
|
||||
/// ssl握手
|
||||
void ssl(Channel channel, HostAndPort hostAndPort, Uint8List data) async {
|
||||
try {
|
||||
Channel remoteChannel = channel.getAttribute(channel.id);
|
||||
|
||||
remoteChannel.secureSocket = await SecureSocket.secure(remoteChannel.socket,
|
||||
host: hostAndPort.host, onBadCertificate: (certificate) => true);
|
||||
Channel? remoteChannel = channel.getAttribute(channel.id);
|
||||
if (remoteChannel != null) {
|
||||
remoteChannel.secureSocket = await SecureSocket.secure(remoteChannel.socket,
|
||||
host: hostAndPort.host, onBadCertificate: (certificate) => true);
|
||||
}
|
||||
|
||||
//ssl自签证书
|
||||
var certificate = await CertificateManager.getCertificateContext(hostAndPort.host);
|
||||
@@ -139,7 +142,7 @@ class Client extends Network {
|
||||
host = host.substring(host.lastIndexOf(":") + 1, host.length - 1);
|
||||
}
|
||||
|
||||
return Socket.connect(host, hostAndPort.port).then((socket) {
|
||||
return Socket.connect(host, hostAndPort.port, timeout: const Duration(seconds: 3)).then((socket) {
|
||||
if (socket.address.type != InternetAddressType.unix) {
|
||||
socket.setOption(SocketOption.tcpNoDelay, true);
|
||||
}
|
||||
|
||||
12
pubspec.lock
12
pubspec.lock
@@ -482,18 +482,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e"
|
||||
sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.1.12"
|
||||
version: "6.1.14"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025"
|
||||
sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.0.38"
|
||||
version: "6.1.0"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -522,10 +522,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea
|
||||
sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.5"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -21,7 +21,7 @@ dependencies:
|
||||
url: https://gitee.com/wanghongenpin/flutter-plugins.git
|
||||
path: packages/desktop_multi_window
|
||||
path_provider: ^2.1.1
|
||||
url_launcher: ^6.1.12
|
||||
url_launcher: ^6.1.14
|
||||
proxy_manager: ^0.0.3
|
||||
qr_flutter: ^4.1.0
|
||||
easy_permission: ^1.0.0
|
||||
|
||||
Reference in New Issue
Block a user