mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-20 16:15:47 +08:00
扫码连接终端
This commit is contained in:
@@ -27,7 +27,7 @@ class ProxyServer {
|
||||
EventListener? listener;
|
||||
RequestRewrites requestRewrites = RequestRewrites();
|
||||
|
||||
List<Function> _initializedListeners = [];
|
||||
final List<Function> _initializedListeners = [];
|
||||
|
||||
ProxyServer({this.listener});
|
||||
|
||||
|
||||
@@ -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<void> 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<Uint8List> {
|
||||
_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<ServerSocket> stop() async {
|
||||
if (!isRunning) return serverSocket;
|
||||
isRunning = false;
|
||||
return serverSocket.close();
|
||||
await serverSocket.close();
|
||||
return serverSocket;
|
||||
}
|
||||
}
|
||||
|
||||
class Client extends Network {
|
||||
Future<Channel> 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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<HttpRequest> {
|
||||
|
||||
@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<HttpRequest> {
|
||||
|
||||
/// 转发请求
|
||||
Future<void> 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<HttpRequest> {
|
||||
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<HttpResponse> {
|
||||
@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<Object> {
|
||||
|
||||
class HttpClients {
|
||||
/// 建立连接
|
||||
static Future<Channel> connect(HostAndPort hostAndPort, ChannelHandler<HttpResponse> handler) async {
|
||||
static Future<Channel> connect(HostAndPort hostAndPort, ChannelHandler handler) async {
|
||||
var client = Client()
|
||||
..initChannel((channel) => channel.pipeline.handle(HttpResponseCodec(), HttpRequestCodec(), handler));
|
||||
|
||||
return client.connect(hostAndPort);
|
||||
}
|
||||
|
||||
static Future<HttpResponse> get(String url, {Duration duration = const Duration(seconds: 3)}) async {
|
||||
var httpResponseHandler = HttpResponseHandler();
|
||||
|
||||
var client = Client()
|
||||
..initChannel((channel) => channel.pipeline.handle(HttpResponseCodec(), HttpRequestCodec(), httpResponseHandler));
|
||||
|
||||
Channel channel = await client.connect(HostAndPort.of(url));
|
||||
HttpRequest msg = HttpRequest(HttpMethod.get, url);
|
||||
|
||||
await channel.write(msg);
|
||||
|
||||
return httpResponseHandler.getResponse(duration).whenComplete(() => channel.close());
|
||||
}
|
||||
}
|
||||
|
||||
class HttpResponseHandler extends ChannelHandler<HttpResponse> {
|
||||
final Completer<HttpResponse> _completer = Completer<HttpResponse>();
|
||||
|
||||
@override
|
||||
void channelRead(Channel channel, HttpResponse msg) {
|
||||
log.i("[${channel.id}] Response ${msg.bodyAsString}");
|
||||
_completer.complete(msg);
|
||||
channel.close();
|
||||
}
|
||||
|
||||
Future<HttpResponse> getResponse(Duration duration) {
|
||||
return _completer.future.timeout(duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ class HttpRequestCodec extends HttpCodec<HttpRequest> {
|
||||
@override
|
||||
HttpRequest createMessage(List<String> reqLine) {
|
||||
HttpMethod httpMethod = HttpMethod.valueOf(reqLine[0]);
|
||||
return HttpRequest(httpMethod, reqLine[1], reqLine[2]);
|
||||
return HttpRequest(httpMethod, reqLine[1], protocolVersion: reqLine[2]);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -58,7 +58,7 @@ class HttpRequest extends HttpMessage {
|
||||
String? remoteDomain;
|
||||
HttpResponse? response;
|
||||
|
||||
HttpRequest(this.method, this.uri, String protocolVersion) : super(protocolVersion);
|
||||
HttpRequest(this.method, this.uri, {String protocolVersion = "HTTP/1.1"}) : super(protocolVersion);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/// 2023/5/23
|
||||
interface class AttributeKeys {
|
||||
static const String host = "HOST";
|
||||
static const String uri= "URI";
|
||||
static const String request= "REQUEST";
|
||||
static const String uri = "URI";
|
||||
static const String request = "REQUEST";
|
||||
static const String remote = "REMOTE";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user