This commit is contained in:
snltty
2024-05-01 14:34:43 +08:00
parent 2b087144d3
commit a98a92d88b
25 changed files with 363 additions and 127 deletions

View File

@@ -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);
}
}

View File

@@ -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">

View File

@@ -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);
}

View File

@@ -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 = ()=>{

View File

@@ -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;

View File

@@ -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>

View 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>

View File

@@ -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)
{
}
}
}

View File

@@ -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>

View File

@@ -1,4 +1,5 @@
using cmonitor.plugins.hijack.report.hijack;
using common.libs;
namespace cmonitor.plugins.hijack.report
{
@@ -20,7 +21,14 @@ namespace cmonitor.plugins.hijack.report
public void Start()
{
hijackController.Start();
try
{
hijackController.Start();
}
catch (Exception ex)
{
Logger.Instance.Error(ex);
}
}
public void Stop()
{

View File

@@ -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);

View File

@@ -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
{

View File

@@ -1,6 +1,7 @@
using cmonitor.config;
using cmonitor.server;
using common.libs;
using common.libs.extends;
using MemoryPack;
namespace cmonitor.plugins.signin.messenger

View File

@@ -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,27 +93,36 @@ namespace cmonitor.plugins.tunnel
{
Task.Run(async () =>
{
TunnelTransportState state = await tunnelTransfer.ConnectAsync(param.Content,"test");
if(state != null)
try
{
var socket = state.ConnectedObject as Socket;
for (int i = 0; i < 10; i++)
TunnelTransportState state = await tunnelTransfer.ConnectAsync(param.Content, "test");
if (state != null)
{
socket.Send(BitConverter.GetBytes(i));
await Task.Delay(10);
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+"");
}
});
}
private void TunnelTest()
{
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)}");
});
}
};

View File

@@ -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.");

View File

@@ -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;
}
@@ -81,11 +80,10 @@ namespace cmonitor.plugins.tunnel
Local = localInfo,
Remote = remoteInfo,
};
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)
{
@@ -214,7 +213,7 @@ namespace cmonitor.plugins.tunnel
private void OnConnectFail(string machineName)
{
if (Logger.Instance.LoggerLevel <= LoggerTypes.DEBUG)
{
{
Logger.Instance.Error($"tunnel connect {machineName} fail");
}
CheckDic(machineName, out TunnelConnectInfo info);

View File

@@ -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)

View File

@@ -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
{

View File

@@ -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
AsyncUserToken token = new AsyncUserToken
{
UserToken = new AsyncUserToken
{
SourceSocket = socket,
State = state,
Saea = acceptEventArg
},
SourceSocket = socket,
State = state,
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,14 +96,14 @@ namespace cmonitor.plugins.tunnel.server
{
if (e.AcceptSocket != null)
{
AsyncUserToken token = e.UserToken as AsyncUserToken;
if (e.AcceptSocket.RemoteEndPoint != null)
{
acceptBinds.AddOrUpdate(e.AcceptSocket.GetHashCode(), e, (a, b) => e);
acceptBinds.TryRemove((token.SourceSocket.LocalEndPoint as IPEndPoint).Port, out _);
OnTcpConnected(token.State, e.AcceptSocket);
StartAccept(e);
AsyncUserToken token = (AsyncUserToken)e.UserToken;
OnTcpConnected(token.State, e.AcceptSocket);
}
}
StartAccept(e);
}
private void ReceiveCallbackUdp(IAsyncResult result)
{
@@ -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()
{

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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++)
{
//全部完成,但是没有连接成功的
if (results.Count(c => c.IsCompleted && (c.AsyncState as Socket).Connected == false) == results.Count())
{
return null;
}
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 = results.FirstOrDefault(c => c.IsCompleted && (c.AsyncState as Socket).Connected);
if (result != null)
IAsyncResult result = targetSocket.BeginConnect(ep, null, null);
for (int i = 0; i < 25; i++)
{
if (result.IsCompleted)
{
break;
}
await Task.Delay(20);
}
try
{
if (result.IsCompleted == false)
{
targetSocket.SafeClose();
continue;
}
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; }
}
}
}

View File

@@ -1,6 +1,5 @@
using common.libs.extends;
using MemoryPack;
using System.Linq;
using System.Net;
namespace cmonitor.serializes

View File

@@ -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)
{

View File

@@ -395,7 +395,14 @@ namespace common.libs.websocket
}
public int SendRaw(Memory<byte> buffer)
{
return Socket.Send(buffer.Span, SocketFlags.None);
try
{
return Socket.Send(buffer.Span, SocketFlags.None);
}
catch (Exception)
{
}
return 0;
}
public int SendFrame(WebSocketFrameRemarkInfo remark)
{