Skip to content

Commit

Permalink
手机端外部代理配置是否展示抓包
Browse files Browse the repository at this point in the history
  • Loading branch information
wanghongenpin committed Nov 23, 2023
1 parent 08decff commit 496b676
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 13 deletions.
1 change: 0 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ android {

minifyEnabled true
shrinkResources true

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
Expand Down
75 changes: 75 additions & 0 deletions android/app/src/main/kotlin/com/network/proxy/vpn/util/TLS.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.network.proxy.vpn.util

import java.nio.ByteBuffer
import kotlin.math.min


class TLS {

companion object {
/**
* 从TLS Client Hello 解析域名
*/
fun getDomain(buffer: ByteBuffer): String? {
var offset = buffer.position()
val limit = buffer.limit()
//TLS Client Hello
if (buffer[offset].toInt() != 0x16) return null
//Skip 43 byte header
offset += 43
if (limit < (offset + 1)) return null

//read session id
val sessionIDLength = buffer[offset++]
offset += sessionIDLength

//read cipher suites
if (offset + 2 > limit) return null
val cipherSuitesLength = buffer.getShort(offset)
offset += 2
offset += cipherSuitesLength

//read Compression method.
if (offset + 1 > limit) return null
val compressionMethodLength = buffer[offset++].toInt() and 0xFF
offset += compressionMethodLength
if (offset > limit) return null

//read Extensions
if (offset + 2 > limit) return null

val extensionsLength = buffer.getShort(offset)
offset += 2
if (offset + extensionsLength > limit) return null

var end: Int = offset + extensionsLength
end = min(end, limit)
while (offset + 4 <= end) {
val extensionType = buffer.getShort(offset)
val extensionLength = buffer.getShort(offset + 2)
offset += 4
//server_name
if (extensionType.toInt() == 0) {
if (offset + 5 > limit) return null
val serverNameListLength = buffer.getShort(offset)
offset += 2
if (offset > limit) return null
if (offset + serverNameListLength > limit) return null

val serverNameType = buffer[offset++]
val serverNameLength = buffer.getShort(offset)
offset += 2
if (offset > limit || serverNameType.toInt() != 0) return null
if (offset + serverNameLength > limit) return null
val serverNameBytes = ByteArray(serverNameLength.toInt())
buffer.get(serverNameBytes)
return String(serverNameBytes)
} else {
offset += extensionLength
}
}
return null
}
}

}
15 changes: 11 additions & 4 deletions lib/network/bin/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ class Configuration {
static Future<Configuration> get instance async {
if (_instance == null) {
Configuration configuration = Configuration._();
await configuration.initConfig();
try {
await configuration.initConfig();
} catch (e) {
logger.e('初始化配置失败', error: e);
}
_instance = configuration;
}
return _instance!;
Expand All @@ -70,7 +74,12 @@ class Configuration {
/// 初始化配置
Future<void> initConfig() async {
// 读取配置文件
await _loadConfig();
try {
await _loadConfig();
} catch (e) {
logger.e('加载配置文件失败', error: e);
}
await _loadRequestRewriteConfig();
}

String? userHome;
Expand Down Expand Up @@ -131,8 +140,6 @@ class Configuration {
appWhitelist = List<String>.from(config['appWhitelist'] ?? []);
HostFilter.whitelist.load(config['whitelist']);
HostFilter.blacklist.load(config['blacklist']);

await _loadRequestRewriteConfig();
}

/// 加载请求重写配置文件
Expand Down
8 changes: 6 additions & 2 deletions lib/network/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class Channel {
}
await _socket.flush();
} catch (e, t) {
print(getAttribute(id)._attributes);
// print(getAttribute(id)._attributes);
print(e);
print(t);
} finally {
Expand Down Expand Up @@ -145,7 +145,11 @@ class Channel {
return _attributes[key] as T;
}

void putAttribute(String key, Object value) {
void putAttribute(String key, Object? value) {
if (value == null) {
_attributes.remove(key);
return;
}
_attributes[key] = value;
}

Expand Down
5 changes: 5 additions & 0 deletions lib/network/host_port.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class HostAndPort {
/// 代理信息
class ProxyInfo {
bool enabled = false;

//是否展示抓包
bool capturePacket = true;
String host = '127.0.0.1';
int? port;

Expand All @@ -103,13 +106,15 @@ class ProxyInfo {

ProxyInfo.fromJson(Map<String, dynamic> json) {
enabled = json['enabled'] == true;
capturePacket = json['capturePacket'] ?? true;
host = json['host'];
port = json['port'];
}

Map<String, dynamic> toJson() {
return {
'enabled': enabled,
'capturePacket': capturePacket,
'host': host,
'port': port,
};
Expand Down
23 changes: 21 additions & 2 deletions lib/network/network.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'dart:typed_data';
import 'package:network_proxy/network/bin/configuration.dart';
import 'package:network_proxy/network/channel.dart';
import 'package:network_proxy/network/handler.dart';
import 'package:network_proxy/network/http_client.dart';
import 'package:network_proxy/network/util/attribute_keys.dart';
import 'package:network_proxy/network/util/crts.dart';
import 'package:network_proxy/network/util/host_filter.dart';
Expand Down Expand Up @@ -57,7 +58,13 @@ class Network {

//外部代理信息
if (configuration?.externalProxy?.enabled == true) {
channel.putAttribute(AttributeKeys.proxyInfo, configuration!.externalProxy!);
ProxyInfo externalProxy = configuration!.externalProxy!;
if (externalProxy.capturePacket == true) {
channel.putAttribute(AttributeKeys.proxyInfo, externalProxy);
} else {
//不抓包直接转发
channel.putAttribute(AttributeKeys.remote, HostAndPort.host(externalProxy.host, externalProxy.port!));
}
}

HostAndPort? hostAndPort = channel.getAttribute(AttributeKeys.host);
Expand All @@ -71,7 +78,7 @@ class Network {
}

//ssl握手
if (hostAndPort?.isSsl() == true || (data.length > 2 && data.first == 0x16 && data[1] == 0x03)) {
if (hostAndPort?.isSsl() == true || TLS.isTLSClientHello(data)) {
if (hostAndPort?.scheme == HostAndPort.httpScheme) {
hostAndPort?.scheme = HostAndPort.httpsScheme;
}
Expand All @@ -92,12 +99,24 @@ class Network {
}
String? host = hostAndPort?.host;
host ??= TLS.getDomain(data);

if (HostFilter.filter(host)) {
remoteChannel =
remoteChannel ?? await HttpClients.startConnect(HostAndPort.host(host!, 443), RelayHandler(channel));
relay(channel, remoteChannel);
channel.pipeline.channelRead(channel, data);
return;
}

//ssl自签证书
var certificate = await CertificateManager.getCertificateContext(host!);
//服务端等待客户端ssl握手
channel.secureSocket = await SecureSocket.secureServer(channel.socket, certificate, bufferedData: data);
} catch (error, trace) {
if (error is HandshakeException) {
String? host = hostAndPort?.host;
host ??= TLS.getDomain(data);
channel.putAttribute(AttributeKeys.host, host == null ? null : HostAndPort.host(host, 443));
await subscription?.cancel();
}
channel.pipeline.exceptionCaught(channel, error, trace: trace);
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/desktop/toolbar/setting/filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class _DomainFilterState extends State<DomainFilter> {
if (host != null && host!.isNotEmpty) {
try {
changed = true;
widget.hostList.add(host!);
widget.hostList.add(host!.trim());
setState(() {});
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.toString())));
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/mobile/setting/filter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class _DomainFilterState extends State<DomainFilter> {
if (host != null && host!.isNotEmpty) {
try {
changed = true;
widget.hostList.add(host!);
widget.hostList.add(host!.trim());
setState(() {});
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.toString())));
Expand Down
12 changes: 11 additions & 1 deletion lib/ui/mobile/setting/proxy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class _ExternalProxyDialogState extends State<ExternalProxyDialog> {
child: Column(mainAxisSize: MainAxisSize.min, children: [
const SizedBox(height: 10),
Row(children: [
const Text("是否启用:"),
const Expanded(flex: 2, child: Text("是否启用:")),
Expanded(
child: Switch(
value: externalProxy.enabled,
Expand All @@ -97,6 +97,16 @@ class _ExternalProxyDialogState extends State<ExternalProxyDialog> {
},
))
]),
Row(children: [
const Expanded(flex: 2, child: Text("手机端是否展示抓包:")),
Expanded(
child: Switch(
value: externalProxy.capturePacket,
onChanged: (val) {
setState(() => externalProxy.capturePacket = val);
},
))
]),
Row(children: [
const Text("地址:"),
Expanded(
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: network_proxy
description: ProxyPin
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.4+1
version: 1.0.5+1

environment:
sdk: '>=3.0.2 <4.0.0'
Expand Down

0 comments on commit 496b676

Please sign in to comment.