mirror of
https://github.com/snltty/linker.git
synced 2025-10-29 03:32:32 +08:00
更新
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using cmonitor.plugins.tunnel.server;
|
||||
using cmonitor.plugins.tunnel.transport;
|
||||
using cmonitor.serializes;
|
||||
using MemoryPack;
|
||||
using System.Net;
|
||||
@@ -11,10 +13,18 @@ namespace cmonitor.tests
|
||||
public void Serialize()
|
||||
{
|
||||
MemoryPackFormatterProvider.Register(new IPEndPointFormatter());
|
||||
MemoryPackIPEndPointSerializeInfo info = new MemoryPackIPEndPointSerializeInfo { EP = new IPEndPoint(IPAddress.Loopback, 12345) };
|
||||
MemoryPackIPEndPointSerializeInfo info1 = MemoryPackSerializer.Deserialize<MemoryPackIPEndPointSerializeInfo>(MemoryPackSerializer.Serialize(info));
|
||||
TunnelTransportInfo info = new TunnelTransportInfo
|
||||
{
|
||||
Direction = TunnelTransportDirection.Reverse,
|
||||
Local = new TunnelTransportExternalIPInfo { Local = new IPEndPoint(IPAddress.Loopback, 12345), Remote = new IPEndPoint(IPAddress.Loopback, 12345), MachineName = "111", RouteLevel = 1 },
|
||||
Remote = new TunnelTransportExternalIPInfo { Local = new IPEndPoint(IPAddress.Loopback, 12345), Remote = new IPEndPoint(IPAddress.Loopback, 12345), MachineName = "111", RouteLevel = 1 },
|
||||
TransactionId = "111",
|
||||
TransportName = "111",
|
||||
TransportType = System.Net.Sockets.ProtocolType.Tcp
|
||||
};
|
||||
TunnelTransportInfo info1 = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(MemoryPackSerializer.Serialize(info));
|
||||
|
||||
Assert.AreEqual(info.EP, info1.EP);
|
||||
Assert.AreEqual(info.Local.Local, info1.Local.Local);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<div class="app-wrap flex flex-column flex-nowrap">
|
||||
<div class="head"><Head></Head></div>
|
||||
<div class="body flex-1">
|
||||
<div class="body flex-1 relative">
|
||||
<router-view/>
|
||||
</div>
|
||||
<div class="status">
|
||||
|
||||
@@ -13,6 +13,13 @@ export const updateConfigSetServers = (servers) => {
|
||||
export const getSignInfo = () => {
|
||||
return sendWebsocketMsg('tunnel/signininfo');
|
||||
}
|
||||
export const getSignList = (data) => {
|
||||
return sendWebsocketMsg('tunnel/SignInList', data);
|
||||
}
|
||||
export const updateSignInDel = (machineName) => {
|
||||
return sendWebsocketMsg('tunnel/signindel', machineName);
|
||||
}
|
||||
|
||||
export const updateTunnelConnect = (machineName) => {
|
||||
return sendWebsocketMsg('tunnel/TunnelConnect', machineName);
|
||||
}
|
||||
|
||||
@@ -46,16 +46,21 @@ export default {
|
||||
const state = reactive({
|
||||
api: route.query.api ? `${window.location.hostname}:${route.query.api}` : (localStorage.getItem('api') || `${window.location.hostname}:1805`),
|
||||
apipsd: route.query.apipsd ? `${route.query.apipsd}` : (localStorage.getItem('apipsd') || `snltty`),
|
||||
groupid: route.query.groupid ? `${route.query.groupid}` : (localStorage.getItem('groupid') || `snltty`),
|
||||
showPort: false
|
||||
});
|
||||
localStorage.setItem('api', state.api);
|
||||
localStorage.setItem('apipsd', state.apipsd);
|
||||
localStorage.setItem('groupid', state.groupid);
|
||||
globalData.value.groupid = state.groupid;
|
||||
const showPort = computed(() => globalData.value.connected == false && state.showPort);
|
||||
|
||||
const handleConnect = () => {
|
||||
initWebsocket(`ws://${state.api}`,state.apipsd);
|
||||
localStorage.setItem('api', state.api);
|
||||
localStorage.setItem('apipsd', state.apipsd);
|
||||
localStorage.setItem('groupid', state.groupid);
|
||||
globalData.value.groupid = state.groupid;
|
||||
}
|
||||
|
||||
const _getConfig = ()=>{
|
||||
|
||||
@@ -9,7 +9,8 @@ export const provideGlobalData = () => {
|
||||
connected: false,
|
||||
updateFlag: false,
|
||||
config: { Common: {}, Client: {} },
|
||||
signin: { Connected: false, Connecting: false }
|
||||
signin: { Connected: false, Connecting: false },
|
||||
groupid: ''
|
||||
});
|
||||
subWebsocketState((state) => {
|
||||
globalData.value.connected = state;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<div class="home"></div>
|
||||
<div class="home absolute">
|
||||
<List></List>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import List from './List.vue'
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {}
|
||||
components: {List}
|
||||
}
|
||||
</script>
|
||||
|
||||
108
cmonitor.web.client/src/views/List.vue
Normal file
108
cmonitor.web.client/src/views/List.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="home-list-wrap absolute" ref="wrap">
|
||||
<el-table :data="state.page.List" border style="width: 100%" :height="`${state.height}px`" size="small">
|
||||
<el-table-column prop="MachineName" label="设备">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<template v-if="scope.row.Connected">
|
||||
<strong class="green">{{ scope.row.MachineName }}</strong>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{ scope.row.MachineName }}</span>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="IP" label="IP" width="160" />
|
||||
<el-table-column prop="Version" label="版本" width="60" />
|
||||
<el-table-column prop="LastSignIn" label="最后登入" width="140" />
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-button size="small" @click="handleTestTunnel(scope.row.MachineName)">测试</el-button>
|
||||
<el-popconfirm confirm-button-text="确认" cancel-button-text="取消" title="删除不可逆,是否确认?" @confirm="handleDelTunnel(scope.row.MachineName)">
|
||||
<template #reference>
|
||||
<el-button type="danger" size="small">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="page t-c">
|
||||
<div class="page-wrap">
|
||||
<el-pagination small background layout="prev, pager, next"
|
||||
:total="state.page.Count" :page-size="state.page.Request.Size" :current-page="state.page.Request.Page"
|
||||
@current-change="handlePageChange"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {getSignList,updateTunnelConnect,updateSignInDel} from '@/apis/tunnel.js'
|
||||
import {subWebsocketState} from '@/apis/request.js'
|
||||
import {injectGlobalData} from '../provide.js'
|
||||
import {reactive,onMounted, ref, nextTick, onUnmounted} from 'vue'
|
||||
export default {
|
||||
setup(props) {
|
||||
|
||||
const globalData = injectGlobalData();
|
||||
const wrap = ref(null);
|
||||
const state = reactive({
|
||||
page:{
|
||||
Request:{Page:1,Size:10,GroupId:globalData.value.groupid},
|
||||
Count:0,
|
||||
List:[]
|
||||
},
|
||||
height:0,
|
||||
});
|
||||
|
||||
const _getSignList = ()=>{
|
||||
getSignList(state.page.Request).then((res)=>{
|
||||
state.page.Request = res.Request;
|
||||
state.page.Count = res.Count;
|
||||
state.page.List = res.List;
|
||||
}).catch((err)=>{});
|
||||
}
|
||||
const handlePageChange = ()=>{
|
||||
_getSignList();
|
||||
}
|
||||
const resizeTable = ()=>{
|
||||
nextTick(()=>{
|
||||
state.height = wrap.value.offsetHeight - 80;
|
||||
});
|
||||
}
|
||||
const handleTestTunnel = (name)=>{
|
||||
updateTunnelConnect(name);
|
||||
}
|
||||
const handleDelTunnel = (name)=>{
|
||||
updateSignInDel(name).then(()=>{
|
||||
_getSignList();
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
subWebsocketState((state)=>{ if(state)_getSignList();});
|
||||
resizeTable();
|
||||
window.addEventListener('resize',resizeTable);
|
||||
});
|
||||
onUnmounted(()=>{
|
||||
window.removeEventListener('resize',resizeTable);
|
||||
});
|
||||
|
||||
return {
|
||||
state,wrap,handlePageChange,handleTestTunnel,handleDelTunnel
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="stylus" scoped>
|
||||
.home-list-wrap{
|
||||
padding:1rem;
|
||||
|
||||
.green{color:green;}
|
||||
|
||||
.page{padding-top:1rem}
|
||||
.page-wrap{
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -11,18 +11,15 @@ namespace cmonitor.client.api
|
||||
public StartupLevel Level => StartupLevel.Normal;
|
||||
public void AddClient(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
serviceCollection.AddSingleton<IApiClientServer, ApiClientServer>();
|
||||
}
|
||||
|
||||
public void AddServer(ServiceCollection serviceCollection, Config config, Assembly[] assemblies)
|
||||
{
|
||||
serviceCollection.AddSingleton<IApiClientServer, ApiClientServer>();
|
||||
|
||||
}
|
||||
|
||||
public void UseClient(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
Logger.Instance.Info($"start client api server");
|
||||
IApiClientServer clientServer = serviceProvider.GetService<IApiClientServer>();
|
||||
@@ -31,5 +28,10 @@ namespace cmonitor.client.api
|
||||
Logger.Instance.Info($"client api listen:{config.Data.Client.ApiPort}");
|
||||
Logger.Instance.Info($"client api password:{config.Data.Client.ApiPassword}");
|
||||
}
|
||||
|
||||
public void UseServer(ServiceProvider serviceProvider, Config config, Assembly[] assemblies)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net7.0;net8.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net7.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using cmonitor.plugins.hijack.report.hijack;
|
||||
using common.libs;
|
||||
|
||||
namespace cmonitor.plugins.hijack.report
|
||||
{
|
||||
@@ -19,9 +20,16 @@ namespace cmonitor.plugins.hijack.report
|
||||
public ulong TcpReceive => hijackEventHandler.TcpReceive;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
hijackController.Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
}
|
||||
public void Stop()
|
||||
{
|
||||
hijackController.Stop();
|
||||
|
||||
@@ -284,6 +284,7 @@ namespace cmonitor.plugins.hijack.report.hijack
|
||||
{
|
||||
while (dnsDataQueue.TryDequeue(out DnsInfo dns))
|
||||
{
|
||||
if (dns.Len == 0) continue;
|
||||
try
|
||||
{
|
||||
DnsUnpackResultInfo dnsPack = DnsUnpack(dns);
|
||||
|
||||
@@ -3,6 +3,7 @@ using common.libs.database;
|
||||
using MemoryPack;
|
||||
using System.Collections.Concurrent;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Net;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace cmonitor.plugins.signin.messenger
|
||||
@@ -44,7 +45,7 @@ namespace cmonitor.plugins.signin.messenger
|
||||
}
|
||||
public List<SignCacheInfo> Get(string groupId)
|
||||
{
|
||||
return config.Clients.Values.Where(c=>c.GroupId == groupId).ToList();
|
||||
return config.Clients.Values.Where(c => c.GroupId == groupId).ToList();
|
||||
}
|
||||
|
||||
public bool Del(string machineName)
|
||||
@@ -83,26 +84,57 @@ namespace cmonitor.plugins.signin.messenger
|
||||
public ConcurrentDictionary<string, SignCacheInfo> Clients { get; set; } = new ConcurrentDictionary<string, SignCacheInfo>();
|
||||
}
|
||||
|
||||
public sealed class SignCacheInfo
|
||||
[MemoryPackable]
|
||||
public sealed partial class SignCacheInfo
|
||||
{
|
||||
public string MachineName { get; set; }
|
||||
public string Version { get; set; } = "1.0.0.0";
|
||||
public string GroupId { get; set; } = "snltty";
|
||||
public DateTime LastSignIn { get; set; } = DateTime.Now;
|
||||
|
||||
public Dictionary<string, string> Args { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
|
||||
private IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0);
|
||||
[MemoryPackAllowSerialize]
|
||||
public IPEndPoint IP
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Connection != null)
|
||||
{
|
||||
ip = Connection.Address;
|
||||
}
|
||||
return ip;
|
||||
}
|
||||
set
|
||||
{
|
||||
ip = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool connected = false;
|
||||
public bool Connected
|
||||
{
|
||||
get
|
||||
{
|
||||
return Connection != null && Connection.Connected == true;
|
||||
if (Connection != null)
|
||||
{
|
||||
connected = Connection.Connected == true;
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
set
|
||||
{
|
||||
connected = value;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
[MemoryPackIgnore]
|
||||
public IConnection Connection { get; set; }
|
||||
}
|
||||
|
||||
|
||||
[MemoryPackable]
|
||||
public sealed partial class SignInfo
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using cmonitor.config;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
|
||||
namespace cmonitor.plugins.signin.messenger
|
||||
|
||||
@@ -5,6 +5,7 @@ using cmonitor.plugins.signin.messenger;
|
||||
using cmonitor.plugins.tunnel.server;
|
||||
using cmonitor.plugins.tunnel.transport;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
using common.libs.api;
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
@@ -68,7 +69,6 @@ namespace cmonitor.plugins.tunnel
|
||||
Payload = MemoryPackSerializer.Serialize(param.Content)
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<SignInListResponseInfo> SignInList(ApiControllerParamsInfo param)
|
||||
{
|
||||
SignInListRequestInfo request = param.Content.DeJson<SignInListRequestInfo>();
|
||||
@@ -84,6 +84,7 @@ namespace cmonitor.plugins.tunnel
|
||||
}
|
||||
return new SignInListResponseInfo { };
|
||||
}
|
||||
|
||||
public Dictionary<string, TunnelConnectInfo> TunnelConnections(ApiControllerParamsInfo param)
|
||||
{
|
||||
return tunnelTransfer.Connections;
|
||||
@@ -92,15 +93,24 @@ namespace cmonitor.plugins.tunnel
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
TunnelTransportState state = await tunnelTransfer.ConnectAsync(param.Content,"test");
|
||||
if(state != null)
|
||||
try
|
||||
{
|
||||
TunnelTransportState state = await tunnelTransfer.ConnectAsync(param.Content, "test");
|
||||
if (state != null)
|
||||
{
|
||||
var socket = state.ConnectedObject as Socket;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Logger.Instance.Debug($"tunnel [test] send {i}");
|
||||
socket.Send(BitConverter.GetBytes(i));
|
||||
await Task.Delay(10);
|
||||
}
|
||||
socket.SafeClose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex+"");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -108,11 +118,11 @@ namespace cmonitor.plugins.tunnel
|
||||
{
|
||||
tunnelTransfer.OnConnected += (TunnelTransportState state) =>
|
||||
{
|
||||
if(state.TransactionId == "test" && state.TransportType == ProtocolType.Tcp)
|
||||
if (state.TransactionId == "test" && state.TransportType == ProtocolType.Tcp)
|
||||
{
|
||||
tunnelBindServer.BindReceive(state.ConnectedObject as Socket, null, async (token,data) =>
|
||||
{
|
||||
Console.WriteLine(BitConverter.ToInt32(data.Span));
|
||||
Logger.Instance.Debug($"tunnel [{state.TransactionId}] receive {BitConverter.ToInt32(data.Span)}");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace cmonitor.plugins.tunnel
|
||||
|
||||
serviceCollection.AddSingleton<TunnelTransfer>();
|
||||
serviceCollection.AddSingleton<TunnelBindServer>();
|
||||
serviceCollection.AddSingleton<ITransport, TransportTcpNutssb>();
|
||||
serviceCollection.AddSingleton<TransportTcpNutssb>();
|
||||
|
||||
|
||||
Logger.Instance.Info($"tunnel route level getting.");
|
||||
|
||||
@@ -5,11 +5,11 @@ using cmonitor.plugins.tunnel.messenger;
|
||||
using cmonitor.plugins.tunnel.transport;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Transactions;
|
||||
|
||||
namespace cmonitor.plugins.tunnel
|
||||
{
|
||||
@@ -46,7 +46,6 @@ namespace cmonitor.plugins.tunnel
|
||||
item.OnConnectBegin = OnConnectBegin;
|
||||
item.OnConnecting = OnConnecting;
|
||||
item.OnConnected = _OnConnected;
|
||||
item.OnConnected += OnConnected;
|
||||
item.OnDisConnected = OnDisConnected;
|
||||
item.OnConnectFail = OnConnectFail;
|
||||
}
|
||||
@@ -85,7 +84,6 @@ namespace cmonitor.plugins.tunnel
|
||||
TunnelTransportState state = await transport.ConnectAsync(tunnelTransportInfo);
|
||||
if (state != null)
|
||||
{
|
||||
|
||||
_OnConnected(state);
|
||||
return state;
|
||||
}
|
||||
@@ -106,7 +104,7 @@ namespace cmonitor.plugins.tunnel
|
||||
if (_transports != null)
|
||||
{
|
||||
_transports.OnFail(tunnelTransportInfo);
|
||||
OnConnectFail(tunnelTransportInfo.FromMachineName);
|
||||
OnConnectFail(tunnelTransportInfo.Remote.MachineName);
|
||||
}
|
||||
}
|
||||
public async Task<TunnelTransportExternalIPInfo> Info(TunnelTransportExternalIPRequestInfo request)
|
||||
@@ -187,7 +185,7 @@ namespace cmonitor.plugins.tunnel
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
Logger.Instance.Debug($"tunnel connect from {tunnelTransportInfo.Local.MachineName}");
|
||||
Logger.Instance.Debug($"tunnel connect from {tunnelTransportInfo.Local.MachineName}->{tunnelTransportInfo.ToJson()}");
|
||||
}
|
||||
CheckDic(tunnelTransportInfo.Local.MachineName, out TunnelConnectInfo info);
|
||||
info.Status = TunnelConnectStatus.Connecting;
|
||||
@@ -203,6 +201,7 @@ namespace cmonitor.plugins.tunnel
|
||||
info.Status = TunnelConnectStatus.Connected;
|
||||
info.State = state;
|
||||
Interlocked.Exchange(ref connectionsChangeFlag, 1);
|
||||
OnConnected(state);
|
||||
}
|
||||
private void OnDisConnected(TunnelTransportState state)
|
||||
{
|
||||
|
||||
@@ -17,16 +17,18 @@ namespace cmonitor.plugins.tunnel.compact
|
||||
socket.IPv6Only(server.AddressFamily, false);
|
||||
await socket.ConnectAsync(server).WaitAsync(TimeSpan.FromSeconds(5));
|
||||
|
||||
byte[] bytes = new byte[20];
|
||||
byte[] bytes = new byte[128];
|
||||
int length = await socket.ReceiveAsync(bytes.AsMemory(), SocketFlags.None);
|
||||
if (length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IPEndPoint local = socket.LocalEndPoint as IPEndPoint;
|
||||
socket.SafeClose();
|
||||
TunnelExternalIPInfo tunnelExternalIPInfo = MemoryPackSerializer.Deserialize<TunnelExternalIPInfo>(bytes.AsSpan(0,length));
|
||||
|
||||
return new TunnelCompactIPEndPoint { Local = socket.LocalEndPoint as IPEndPoint, Remote = tunnelExternalIPInfo.ExternalIP };
|
||||
return new TunnelCompactIPEndPoint { Local = local, Remote = tunnelExternalIPInfo.ExternalIP };
|
||||
}
|
||||
|
||||
public async Task<TunnelCompactIPEndPoint> GetUdpExternalIPAsync(IPEndPoint server)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using cmonitor.client;
|
||||
using cmonitor.config;
|
||||
using cmonitor.plugins.signin.messenger;
|
||||
using cmonitor.plugins.signin.messenger;
|
||||
using cmonitor.plugins.tunnel.transport;
|
||||
using cmonitor.server;
|
||||
using common.libs;
|
||||
@@ -21,6 +19,10 @@ namespace cmonitor.plugins.tunnel.messenger
|
||||
public void Begin(IConnection connection)
|
||||
{
|
||||
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
TunnelTransportExternalIPInfo local = tunnelTransportInfo.Local;
|
||||
tunnelTransportInfo.Local = tunnelTransportInfo.Remote;
|
||||
tunnelTransportInfo.Remote = local;
|
||||
|
||||
tunnel.OnBegin(tunnelTransportInfo);
|
||||
connection.Write(Helper.TrueArray);
|
||||
}
|
||||
@@ -40,6 +42,10 @@ namespace cmonitor.plugins.tunnel.messenger
|
||||
public void Fail(IConnection connection)
|
||||
{
|
||||
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
TunnelTransportExternalIPInfo local = tunnelTransportInfo.Local;
|
||||
tunnelTransportInfo.Local = tunnelTransportInfo.Remote;
|
||||
tunnelTransportInfo.Remote = local;
|
||||
|
||||
tunnel.OnFail(tunnelTransportInfo);
|
||||
}
|
||||
}
|
||||
@@ -86,7 +92,7 @@ namespace cmonitor.plugins.tunnel.messenger
|
||||
});
|
||||
if (resp.Code == MessageResponeCodes.OK)
|
||||
{
|
||||
connection.Write(MemoryPackSerializer.Serialize(MemoryPackSerializer.Deserialize<TunnelTransportInfo>(resp.Data.Span)));
|
||||
connection.Write(MemoryPackSerializer.Serialize(MemoryPackSerializer.Deserialize<TunnelTransportExternalIPInfo>(resp.Data.Span)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,7 +101,7 @@ namespace cmonitor.plugins.tunnel.messenger
|
||||
public async Task FailForward(IConnection connection)
|
||||
{
|
||||
TunnelTransportInfo tunnelTransportInfo = MemoryPackSerializer.Deserialize<TunnelTransportInfo>(connection.ReceiveRequestWrap.Payload.Span);
|
||||
if (signCaching.Get(tunnelTransportInfo.FromMachineName, out SignCacheInfo cache) && signCaching.Get(connection.Name, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
|
||||
if (signCaching.Get(tunnelTransportInfo.Remote.MachineName, out SignCacheInfo cache) && signCaching.Get(connection.Name, out SignCacheInfo cache1) && cache.GroupId == cache1.GroupId)
|
||||
{
|
||||
await messengerSender.SendOnly(new MessageRequestWrap
|
||||
{
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace cmonitor.plugins.tunnel.server
|
||||
{
|
||||
public sealed class TunnelBindServer
|
||||
{
|
||||
private SocketAsyncEventArgs acceptEventArg;
|
||||
private UdpClient socketUdp;
|
||||
|
||||
public Action<object, Socket> OnTcpConnected { get; set; } = (state, socket) => { };
|
||||
@@ -26,16 +25,18 @@ namespace cmonitor.plugins.tunnel.server
|
||||
socket.ReuseBind(new IPEndPoint(IPAddress.Any, local.Port));
|
||||
socket.Listen(int.MaxValue);
|
||||
|
||||
acceptEventArg = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = new AsyncUserToken
|
||||
AsyncUserToken token = new AsyncUserToken
|
||||
{
|
||||
SourceSocket = socket,
|
||||
State = state,
|
||||
Saea = acceptEventArg
|
||||
},
|
||||
LocalPort = local.Port
|
||||
};
|
||||
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = token,
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
token.Saea = acceptEventArg;
|
||||
acceptBinds.AddOrUpdate(local.Port, acceptEventArg, (a, b) => acceptEventArg);
|
||||
|
||||
acceptEventArg.Completed += IO_Completed;
|
||||
@@ -84,6 +85,9 @@ namespace cmonitor.plugins.tunnel.server
|
||||
case SocketAsyncOperation.Accept:
|
||||
ProcessAccept(e);
|
||||
break;
|
||||
case SocketAsyncOperation.Receive:
|
||||
ProcessReceive(e);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -92,15 +96,15 @@ namespace cmonitor.plugins.tunnel.server
|
||||
{
|
||||
if (e.AcceptSocket != null)
|
||||
{
|
||||
AsyncUserToken token = e.UserToken as AsyncUserToken;
|
||||
|
||||
acceptBinds.AddOrUpdate(e.AcceptSocket.GetHashCode(), e, (a, b) => e);
|
||||
acceptBinds.TryRemove((token.SourceSocket.LocalEndPoint as IPEndPoint).Port, out _);
|
||||
if (e.AcceptSocket.RemoteEndPoint != null)
|
||||
{
|
||||
|
||||
AsyncUserToken token = (AsyncUserToken)e.UserToken;
|
||||
OnTcpConnected(token.State, e.AcceptSocket);
|
||||
StartAccept(e);
|
||||
}
|
||||
}
|
||||
StartAccept(e);
|
||||
}
|
||||
private void ReceiveCallbackUdp(IAsyncResult result)
|
||||
{
|
||||
try
|
||||
@@ -127,7 +131,8 @@ namespace cmonitor.plugins.tunnel.server
|
||||
{
|
||||
SourceSocket = socket,
|
||||
State = state,
|
||||
OnData = dataCallback
|
||||
OnData = dataCallback,
|
||||
LocalPort = (socket.LocalEndPoint as IPEndPoint).Port,
|
||||
};
|
||||
|
||||
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs
|
||||
@@ -200,17 +205,16 @@ namespace cmonitor.plugins.tunnel.server
|
||||
if (e == null || e.UserToken == null) return;
|
||||
|
||||
AsyncUserToken token = e.UserToken as AsyncUserToken;
|
||||
e.UserToken = null;
|
||||
if (token.SourceSocket != null)
|
||||
Socket socket = token.SourceSocket;
|
||||
if (socket != null)
|
||||
{
|
||||
token.Clear();
|
||||
e.Dispose();
|
||||
|
||||
if (acceptBinds.TryRemove(token.SourceSocket.GetHashCode(), out SocketAsyncEventArgs saea))
|
||||
if (acceptBinds.TryRemove(token.LocalPort, out SocketAsyncEventArgs saea1))
|
||||
{
|
||||
CloseClientSocket(saea);
|
||||
OnDisConnected(token.State);
|
||||
CloseClientSocket(saea1);
|
||||
}
|
||||
OnDisConnected(token.State);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,8 +226,10 @@ namespace cmonitor.plugins.tunnel.server
|
||||
public Socket SourceSocket { get; set; }
|
||||
public SocketAsyncEventArgs Saea { get; set; }
|
||||
public object State { get; set; }
|
||||
|
||||
public OnTunnelData OnData { get; set; }
|
||||
|
||||
public int LocalPort { get; set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
|
||||
@@ -78,7 +78,16 @@ namespace cmonitor.plugins.tunnel.server
|
||||
{
|
||||
if (e.AcceptSocket != null)
|
||||
{
|
||||
WriteExternalIP(e);
|
||||
SocketAsyncEventArgs receiveEventArg = new SocketAsyncEventArgs
|
||||
{
|
||||
UserToken = new AsyncUserToken
|
||||
{
|
||||
SourceSocket = e.AcceptSocket
|
||||
},
|
||||
SocketFlags = SocketFlags.None,
|
||||
};
|
||||
|
||||
WriteExternalIP(receiveEventArg);
|
||||
StartAccept(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +87,6 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
public string TransportName { get; set; }
|
||||
|
||||
public TunnelTransportDirection Direction { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[MemoryPackIgnore]
|
||||
public string FromMachineName => Direction == TunnelTransportDirection.Forward ? Remote.MachineName : Local.MachineName;
|
||||
[JsonIgnore]
|
||||
[MemoryPackIgnore]
|
||||
public IPEndPoint BindEP => Direction == TunnelTransportDirection.Forward ? Remote.Local : Local.Local;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,42 +36,45 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
|
||||
tunnelTransportInfo.Direction = TunnelTransportDirection.Forward;
|
||||
await OnSendConnectBegin(tunnelTransportInfo);
|
||||
TunnelTransportState state = await ConnectForward(tunnelTransportInfo.Local, tunnelTransportInfo.Remote, tunnelTransportInfo);
|
||||
TunnelTransportState state = await ConnectForward(tunnelTransportInfo);
|
||||
if (state != null)
|
||||
{
|
||||
//OnConnected(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
TunnelTransportInfo tunnelTransportInfo1 = tunnelTransportInfo.ToJsonFormat().DeJson<TunnelTransportInfo>();
|
||||
tunnelTransportInfo1.Direction = TunnelTransportDirection.Reverse;
|
||||
BindAndTTL(tunnelTransportInfo1.Local, tunnelTransportInfo1.Remote, tunnelTransportInfo1);
|
||||
_ = OnSendConnectBegin(tunnelTransportInfo1);
|
||||
tunnelBindServer.Bind(tunnelTransportInfo1.Local.Local, tunnelTransportInfo1);
|
||||
BindAndTTL(tunnelTransportInfo1);
|
||||
await OnSendConnectBegin(tunnelTransportInfo1);
|
||||
|
||||
state = await WaitReverse(tunnelTransportInfo1);
|
||||
if (state != null)
|
||||
{
|
||||
//OnConnected(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
await OnSendConnectFail(tunnelTransportInfo);
|
||||
OnConnectFail(tunnelTransportInfo1.Remote.MachineName);
|
||||
OnConnectFail(tunnelTransportInfo.Remote.MachineName);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnBegin(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
OnConnectBegin(tunnelTransportInfo);
|
||||
if (tunnelTransportInfo.Direction == TunnelTransportDirection.Forward)
|
||||
{
|
||||
tunnelBindServer.Bind(tunnelTransportInfo.Local.Local, tunnelTransportInfo);
|
||||
}
|
||||
Task.Run(async () =>
|
||||
{
|
||||
if (tunnelTransportInfo.Direction == TunnelTransportDirection.Forward)
|
||||
{
|
||||
BindAndTTL(tunnelTransportInfo.Remote, tunnelTransportInfo.Local, tunnelTransportInfo);
|
||||
BindAndTTL(tunnelTransportInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
TunnelTransportState state = await ConnectForward(tunnelTransportInfo.Remote, tunnelTransportInfo.Local, tunnelTransportInfo);
|
||||
TunnelTransportState state = await ConnectForward(tunnelTransportInfo);
|
||||
if (state != null)
|
||||
{
|
||||
OnConnected(state);
|
||||
@@ -87,74 +90,85 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
|
||||
public void OnFail(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
tunnelBindServer.RemoveBind(tunnelTransportInfo.BindEP.Port);
|
||||
tunnelBindServer.RemoveBind(tunnelTransportInfo.Local.Local.Port);
|
||||
}
|
||||
|
||||
private async Task<TunnelTransportState> ConnectForward(TunnelTransportExternalIPInfo local, TunnelTransportExternalIPInfo remote, TunnelTransportInfo tunnelTransportInfo)
|
||||
private async Task<TunnelTransportState> ConnectForward(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
await Task.Delay(20);
|
||||
//要连接哪些IP
|
||||
IPEndPoint[] eps = new IPEndPoint[] {
|
||||
new IPEndPoint(remote.Local.Address,remote.Local.Port),
|
||||
new IPEndPoint(remote.Local.Address,remote.Remote.Port),
|
||||
new IPEndPoint(remote.Local.Address,remote.Remote.Port+1),
|
||||
new IPEndPoint(remote.Remote.Address,remote.Remote.Port),
|
||||
new IPEndPoint(remote.Remote.Address,remote.Remote.Port+1),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Local.Address,tunnelTransportInfo.Remote.Local.Port),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Local.Address,tunnelTransportInfo.Remote.Remote.Port),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Local.Address,tunnelTransportInfo.Remote.Remote.Port+1),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port+1),
|
||||
};
|
||||
//过滤掉不支持IPV6的情况,去尝试连接
|
||||
IEnumerable<IAsyncResult> results = eps.Where(c => NotIPv6Support(c.Address) == false).Select(ip =>
|
||||
foreach (IPEndPoint ep in eps)
|
||||
{
|
||||
using Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
targetSocket.IPv6Only(ip.Address.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ip.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, local.Local.Port));
|
||||
IAsyncResult result = targetSocket.BeginConnect(ip, null, targetSocket);
|
||||
return result;
|
||||
});
|
||||
//检查一下是否连接成功
|
||||
for (int i = 0; i < 10; i++)
|
||||
Socket targetSocket = new(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
targetSocket.IPv6Only(ep.Address.AddressFamily, false);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ep.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
|
||||
IAsyncResult result = targetSocket.BeginConnect(ep, null, null);
|
||||
|
||||
for (int i = 0; i < 25; i++)
|
||||
{
|
||||
//全部完成,但是没有连接成功的
|
||||
if (results.Count(c => c.IsCompleted && (c.AsyncState as Socket).Connected == false) == results.Count())
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
return null;
|
||||
break;
|
||||
}
|
||||
await Task.Delay(20);
|
||||
}
|
||||
try
|
||||
{
|
||||
if (result.IsCompleted == false)
|
||||
{
|
||||
targetSocket.SafeClose();
|
||||
continue;
|
||||
}
|
||||
|
||||
IAsyncResult result = results.FirstOrDefault(c => c.IsCompleted && (c.AsyncState as Socket).Connected);
|
||||
if (result != null)
|
||||
{
|
||||
targetSocket.EndConnect(result);
|
||||
return new TunnelTransportState
|
||||
{
|
||||
ConnectedObject = result.AsyncState as Socket,
|
||||
ConnectedObject = targetSocket,
|
||||
TransactionId = tunnelTransportInfo.TransactionId,
|
||||
RemoteMachineName = remote.MachineName,
|
||||
RemoteMachineName = tunnelTransportInfo.Remote.MachineName,
|
||||
TransportName = Name,
|
||||
TransportType = Type
|
||||
};
|
||||
}
|
||||
await Task.Delay(10);
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
|
||||
{
|
||||
Logger.Instance.Error(targetSocket.RemoteEndPoint.ToString());
|
||||
Logger.Instance.Error(ex);
|
||||
}
|
||||
targetSocket.SafeClose();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private void BindAndTTL(TunnelTransportExternalIPInfo local, TunnelTransportExternalIPInfo remote, TunnelTransportInfo tunnelTransportInfo)
|
||||
private void BindAndTTL(TunnelTransportInfo tunnelTransportInfo)
|
||||
{
|
||||
tunnelBindServer.Bind(local.Local, tunnelTransportInfo);
|
||||
|
||||
//给对方发送TTL消息
|
||||
IPEndPoint[] eps = new IPEndPoint[] {
|
||||
new IPEndPoint(remote.Local.Address,remote.Local.Port),
|
||||
new IPEndPoint(remote.Local.Address,remote.Remote.Port),
|
||||
new IPEndPoint(remote.Local.Address,remote.Remote.Port+1),
|
||||
new IPEndPoint(remote.Remote.Address,remote.Remote.Port),
|
||||
new IPEndPoint(remote.Remote.Address,remote.Remote.Port+1),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Local.Address,tunnelTransportInfo.Local.Local.Port),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Local.Address,tunnelTransportInfo.Remote.Remote.Port),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Local.Address,tunnelTransportInfo.Remote.Remote.Port+1),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port),
|
||||
new IPEndPoint(tunnelTransportInfo.Remote.Remote.Address,tunnelTransportInfo.Remote.Remote.Port+1),
|
||||
};
|
||||
//过滤掉不支持IPV6的情况
|
||||
IEnumerable<Socket> sockets = eps.Where(c => NotIPv6Support(c.Address) == false).Select(ip =>
|
||||
{
|
||||
using Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
Socket targetSocket = new(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
try
|
||||
{
|
||||
targetSocket.IPv6Only(ip.Address.AddressFamily, false);
|
||||
targetSocket.Ttl = (short)(local.RouteLevel);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ip.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, local.Local.Port));
|
||||
targetSocket.Ttl = (short)(tunnelTransportInfo.Local.RouteLevel + 1);
|
||||
targetSocket.ReuseBind(new IPEndPoint(ip.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any, tunnelTransportInfo.Local.Local.Port));
|
||||
_ = targetSocket.ConnectAsync(ip);
|
||||
return targetSocket;
|
||||
}
|
||||
@@ -190,14 +204,13 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
{
|
||||
TunnelTransportState result = new TunnelTransportState
|
||||
{
|
||||
RemoteMachineName = _state.FromMachineName,
|
||||
RemoteMachineName = _state.Remote.MachineName,
|
||||
TransportType = ProtocolType.Tcp,
|
||||
ConnectedObject = socket,
|
||||
TransactionId = _state.TransactionId,
|
||||
TransportName = _state.TransportName,
|
||||
};
|
||||
|
||||
if (reverseDic.TryRemove(_state.FromMachineName, out TaskCompletionSource<TunnelTransportState> tcs))
|
||||
if (reverseDic.TryRemove(_state.Remote.MachineName, out TaskCompletionSource<TunnelTransportState> tcs))
|
||||
{
|
||||
tcs.SetResult(result);
|
||||
return;
|
||||
@@ -212,12 +225,12 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
{
|
||||
TunnelTransportState result = new TunnelTransportState
|
||||
{
|
||||
RemoteMachineName = _state.FromMachineName,
|
||||
RemoteMachineName = _state.Remote.MachineName,
|
||||
TransportType = ProtocolType.Tcp,
|
||||
TransactionId = _state.TransactionId,
|
||||
TransportName = _state.TransportName,
|
||||
};
|
||||
OnConnected(result);
|
||||
OnDisConnected(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,5 +239,11 @@ namespace cmonitor.plugins.tunnel.transport
|
||||
return ip.AddressFamily == AddressFamily.InterNetworkV6 && (NetworkHelper.IPv6Support == false);
|
||||
}
|
||||
|
||||
public sealed class ConnectResultInfo
|
||||
{
|
||||
public IAsyncResult Result { get; set; }
|
||||
public Socket Socket { get; set; }
|
||||
public bool EndConnected { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using common.libs.extends;
|
||||
using MemoryPack;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
||||
namespace cmonitor.serializes
|
||||
|
||||
@@ -6,6 +6,14 @@ namespace common.libs.extends
|
||||
{
|
||||
public static class SerialzeExtends
|
||||
{
|
||||
private static JsonSerializerOptions jsonSerializerOptions1 = new JsonSerializerOptions
|
||||
{
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All),
|
||||
AllowTrailingCommas = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
Converters = { new IPAddressJsonConverter(), new IPEndpointJsonConverter(), new DateTimeConverter() }
|
||||
};
|
||||
private static JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
|
||||
{
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All),
|
||||
@@ -26,7 +34,7 @@ namespace common.libs.extends
|
||||
};
|
||||
public static string ToJson(this object obj)
|
||||
{
|
||||
return JsonSerializer.Serialize(obj);
|
||||
return JsonSerializer.Serialize(obj, jsonSerializerOptions1);
|
||||
}
|
||||
public static string ToJsonFormat(this object obj)
|
||||
{
|
||||
|
||||
@@ -394,9 +394,16 @@ namespace common.libs.websocket
|
||||
return Socket.Send(buffer, SocketFlags.None);
|
||||
}
|
||||
public int SendRaw(Memory<byte> buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Socket.Send(buffer.Span, SocketFlags.None);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public int SendFrame(WebSocketFrameRemarkInfo remark)
|
||||
{
|
||||
var frame = WebSocketParser.BuildFrameData(remark, out int length);
|
||||
|
||||
Reference in New Issue
Block a user