1 Star 3 Fork 1

apiumc/WebVPN

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Utility.cs 39.88 KB
一键复制 编辑 原始数据 按行查看 历史
apiumc 提交于 2026-01-02 08:06 +08:00 . change
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
using System;
using System.Collections.Generic;
using System.Linq;
using UMC.Data;
using UMC.Net;
using UMC.Web;
using System.Security.Cryptography.X509Certificates;
using UMC.Host;
using UMC.Security;
using System.Runtime.InteropServices;
using NSec.Cryptography;
using System.Net;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Formats.Cbor;
namespace UMC.ITME
{
public class WebResource : UMC.Data.WebResource
{
// public override void Username(Web.WebRequest webRequest, Security.AccessToken Token)
// {
// if (System.Net.IPAddress.TryParse(webRequest.UserHostAddress, out var address))
// {
// Utility.SyncClient(0x08, new StringValue(address.GetAddressBytes()));
// }
// }
public override void Logout(Web.WebRequest webRequest, Security.AccessToken token)
{
if (System.Net.IPAddress.TryParse(webRequest.UserHostAddress, out var address))
{
var doh = token.Get("DoH-Key");
if (String.IsNullOrEmpty(doh) == false)
{
var value = Utility.FromBase64String(doh);
if (value.Length == 16)
{
Utility.SyncClient(0x08, new StringValue(value));
}
}
Utility.SyncClient(0x08, new StringValue(address.GetAddressBytes()));
}
}
public virtual async Task<WebMeta> GetBridgeConfig(StringValue host)
{
var cName = await Bridge.HttpBridgeServier.CName(host);
var webR = Bridge.HttpBridgeServier.Sign(new Uri(UMC.Net.APIProxy.Uri, $"SiteConfig?Domain={host}&CName={cName}").WebRequest());
try
{
using (var mime = await Bridge.HttpBridge.GetAsync(webR))
{
if (UMC.Data.Utility.TryParse(mime.Second.Span, 10, out int value))
{
if (value == (int)HttpStatusCode.OK)
{
var siteD = UMC.Data.JSON.Deserialize<UMC.Web.WebMeta>(mime.Memory.Temp());
return siteD;
}
}
}
}
catch
{
}
return null;
}
public override void Remember(string root, Identity identity, string password)
{
if (String.IsNullOrEmpty(root) == false)
{
DataFactory.Instance().Put(new Entities.Cookie
{
Domain = root,
user_id = identity.Id.Value,
Account = identity.Name,
IndexValue = 0
});
UMC.Data.DataFactory.Instance().Password(SiteConfig.MD5Key(root, identity.Id.Value.ToString(), "0"), password);
}
}
public override void Push(Uri uri, Guid tid, params object[] objs)
{
var str = JSON.Serialize(objs);
var device = Utility.Guid(tid);
foreach (var p in Net.NetSubscribe.Subscribes)
{
try
{
new Uri($"https://{p.Address}/UMC.WS/{device}")
.WebRequest().Post(str, w =>
{
});
}
catch
{
}
}
UMC.Host.HttpWebSocket.Send(tid, str);
}
}
public class Utility : UMC.Data.Utility
{
public static bool IsInternalIP(IPAddress address)
{
return Socks5Server.IsInternalIP(address.GetAddressBytes());
}
public static bool IsInternalIP(ReadOnlySpan<byte> address)
{
return Socks5Server.IsInternalIP(address);
}
[DllImport("libsodium", CallingConvention = CallingConvention.Cdecl)]
internal unsafe static extern int crypto_sign_ed25519_sk_to_curve25519(byte* curve25519_sk, byte* ed25519_sk);
[DllImport("libsodium", CallingConvention = CallingConvention.Cdecl)]
internal unsafe static extern int crypto_sign_ed25519_pk_to_curve25519(byte* curve25519_pk, byte* ed25519_pk);
public static byte[] ToCurvePublicKey(Span<byte> pkEd25519)
{
Span<byte> pcurve25519 = stackalloc byte[32];
unsafe
{
fixed (byte* pk = pkEd25519)
{
fixed (byte* pcur = pcurve25519)
{
crypto_sign_ed25519_pk_to_curve25519(pcur, pk);
}
}
}
return pcurve25519.ToArray();
}
public static bool ApiVerify(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature)
{
var pubKey = NSec.Cryptography.PublicKey.Import(NSec.Cryptography.SignatureAlgorithm.Ed25519, Utility.FromBase64String("XiIeBP6LMDgyJZvULYlTjVRtnk2Xw9Dq6XmNHmYo21Y"), KeyBlobFormat.RawPublicKey);
return SignatureAlgorithm.Ed25519.Verify(pubKey, data, signature);
}
public static void ToCurveSecretKey(Span<byte> skEd, Span<byte> skCurve)
{
unsafe
{
fixed (byte* sked = skEd)
{
fixed (byte* skc = skCurve)
{
crypto_sign_ed25519_sk_to_curve25519(skc, sked);
}
}
}
}
public static void SaveDNS()
{
var dns = new ProviderConfiguration();
var em = UMC.Net.NetProxy.DNS().GetEnumerator();
while (em.MoveNext())
{
if (em.Current.Value.Item2.HasFlag(NetProxy.DNSType.DNS))
{
dns.Add(Provider.Create(em.Current.Key, em.Current.Value.Item2.HasFlag(NetProxy.DNSType.IP6) ? "dns6" : "dns"));
}
else if (em.Current.Value.Item1 == int.MaxValue && em.Current.Value.Item3.Length > 0)
{
dns.Add(Provider.Create(em.Current.Key, em.Current.Value.Item3[0].ToString()));
}
}
UMC.Data.Reflection.Configuration("dns", dns);
}
private const int StackallocThreshold = 512;
internal static byte[] UrlDecode(ReadOnlySpan<byte> bytes)
{
int decodedBytesCount = 0;
int count = bytes.Length;
Span<byte> decodedBytes = count <= StackallocThreshold ? stackalloc byte[StackallocThreshold] : new byte[count];
for (int i = 0; i < count; i++)
{
byte b = bytes[i];
if (b == '+')
{
b = (byte)' ';
}
else if (b == '%' && i < count - 2)
{
int h1 = FromChar(bytes[i + 1]);
int h2 = FromChar(bytes[i + 2]);
if ((h1 | h2) != 0xFF)
{
b = (byte)((h1 << 4) | h2);
i += 2;
}
}
decodedBytes[decodedBytesCount++] = b;
}
return decodedBytes.Slice(0, decodedBytesCount).ToArray();
}
public static int UserAgent(ReadOnlySpan<byte> bytes)
{
var bs = System.Buffers.ArrayPool<byte>.Shared.Rent(bytes.Length + 16);
int size = 0;
try
{
int start = 0;
for (var i = 0; i < bytes.Length; i++)
{
if ('0' <= bytes[i] && bytes[i] <= '9')
{
if (start < i)
{
int len = i - start;
bytes.Slice(start, len).CopyTo(bs.AsSpan(size));
size += len;
}
else
{
start = i + 1;
}
}
}
if (start < bytes.Length)
{
int len = bytes.Length - start;
bytes.Slice(start, len).CopyTo(bs.AsSpan(size));
size += len;
}
using (var md5 = System.Security.Cryptography.MD5.Create())
{
md5.TryComputeHash(bs.AsSpan(0, size), bs.AsSpan(size), out var l);
return Utility.IntParse(bs.AsSpan(size, 16));
}
}
finally
{
System.Buffers.ArrayPool<byte>.Shared.Return(bs);
}
// var ms=÷
}
public static bool IsIP(StringValue stringValue)
{
var spsn = stringValue.Span;
foreach (var s in spsn)
{
switch (s)
{
case 65:
case 66:
case 67:
case 68:
case 69:
case 98:
case 99:
case 100:
case 101:
case 102:
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
case 46:
break;
default:
return false;
}
}
return true;
}
public static StringValue LocalFinger()
{
return HttpsStream.LocalFinger();
}
public static bool IsHost(ReadOnlySpan<byte> host)
{
// var spsn = stringValue.Span;
foreach (var s in host)
{
switch (s)
{
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
case 103:
case 104:
case 105:
case 106:
case 107:
case 108:
case 109:
case 110:
case 111:
case 112:
case 113:
case 114:
case 115:
case 116:
case 117:
case 118:
case 119:
case 120:
case 121:
case 122:
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
case 58:
case 45:
case 46:
break;
default:
return false;
}
}
return true;
}
// public static int FromChar(int c)
// {
// return c >= CharToHexLookup.Length ? 0xFF : CharToHexLookup[c];
// }
// static byte[] CharToHexLookup = new byte[]{
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 15
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 31
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 47
// 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 63
// 0xFF, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 79
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 95
// 0xFF, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 111
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 127
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 143
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 159
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 175
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 191
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 207
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 223
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 239
// 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 255
// };
public static String MD5(System.Guid guid)
{
using (var md5 = System.Security.Cryptography.MD5.Create())
{
return Guid(new System.Guid(md5.ComputeHash(guid.ToByteArray())));
}
}
public static readonly StringValue UmcRequestUserName = new StringValue("Umc-Request-User-Name".UTF8());
public static readonly StringValue UmcRequestUserAlias = new StringValue("Umc-Request-User-Alias".UTF8());
public static readonly StringValue UmcRequestUserRoles = new StringValue("Umc-Request-User-Roles".UTF8());
public static readonly StringValue UmcRequestUserId = new StringValue("Umc-Request-User-Id".UTF8());
public static readonly StringValue UmcRequestUserOrganizes = new StringValue("Umc-Request-User-Organizes".UTF8());
public static readonly StringValue UmcRequestUserTime = new StringValue("Umc-Request-User-Time".UTF8());
public static readonly StringValue UmcRequestUserSign = new StringValue("Umc-Request-User-Sign".UTF8());
// public static String NameValue(NameValueCollection Headers)
// {
// var sb = new StringBuilder();
// for (var i = 0; i < Headers.Count; i++)
// {
// sb.AppendFormat("{0}: {1}", Headers.GetKey(i), Headers.Get(i));
// sb.AppendLine();
// }
// sb.AppendLine();
// return sb.ToString();
// }
public static int HashCode(ReadOnlySpan<byte> Segments)
{
var hash = new HashCode();
hash.AddBytes(Segments);
return hash.ToHashCode();
}
static Web.WebMeta FromValue(int index, Span<byte> html, out int tagEndIndex)
{
tagEndIndex = -1;
var startIndex = 0;
while (index > -1)
{
index--;
switch (html[index])
{
case 32://(byte)' ':
// case (byte)' ':
break;
case 60:
// case (byte)'<':
startIndex = index;
break;
case 34: //'"'
case 39://(byte)'\'':
// case (byte)'\'':
// case (byte)'"':
index = html.LastIndexOf(html[index], index - 1);
break;
}
if (startIndex > 0)
{
break;
}
}
var start = startIndex + 1;
var attrStart = -1;
var attrName = String.Empty;
var webMeta = new Web.WebMeta();
var IsFindTag = true;
while (IsFindTag)
{
start++;
switch (html[start])
{
case 13://(byte)'\r':
case 9:// (byte)'\t':
case 10:// (byte)'\n':
case 32://(byte)' ':
// case (byte)'\r':
// case (byte)'\n':
// case (byte)'\t':
// case (byte)' ':
IsFindTag = false;
webMeta.Put("tag", html.Slice(startIndex + 1, start - startIndex - 1).UTF8());
break;
default:
IsFindTag = start < html.Length;
break;
}
}
var startValue = -1;
while (start < html.Length)
{
switch (html[start])
{
case 13://(byte)'\r':
case 9:// (byte)'\t':
case 10:// (byte)'\n':
case 32://(byte)' ':
// case (byte)'\r':
// case (byte)'\n':
// case (byte)'\t':
// case (byte)' ':
if (startValue == -1)
{
if (attrStart < start - 1 && attrStart > 0)
{
attrName = html.Slice(attrStart, start - attrStart).UTF8();
webMeta.Put(attrName.ToLower(), String.Empty);
}
}
else
{
webMeta.Put(attrName.ToLower(), html.Slice(startValue, start - startValue).UTF8());
startValue = -1;
}
attrStart = start + 1;
break;
case 61:
// case (byte)'=':
if (attrStart < start - 1)
{
attrName = html.Slice(attrStart, start - attrStart).UTF8();
}
attrStart = start + 1;
startValue = attrStart;
break;
case 34: //'"'
case 39://(byte)'\'':
// case (byte)'\'':
// case (byte)'"':
// html.in
// Array.IndexOf(html,html[start]);
var startValueIndex = html.IndexOf(html[start], start + 1);
if (startValueIndex > 0)
{
webMeta.Put(attrName.ToLower(), System.Web.HttpUtility.HtmlDecode(html.Slice(start + 1, startValueIndex - start - 1).UTF8()));
}
start = startValueIndex;
startValue = -1;
attrStart = start + 1;
break;
case 47:
// case (byte)'/':
tagEndIndex = start + 1;
return webMeta;
case 62:
// case (byte)'>':
tagEndIndex = start;
return webMeta;
default:
break;
}
start++;
}
return webMeta;
}
static String FromValue(Span<byte> html, int index, bool isForm, out int endIndex)
{
var ms = FromValue(index, html, out endIndex);
if (ms.ContainsKey("disabled"))
{
return null;
}
switch (ms["tag"])
{
case "input":
var type = ms["type"];
switch (type)
{
case "radio":
case "checkbox":
if (!ms.ContainsKey("checked") && isForm)
{
return null;
}
return ms["value"] ?? "on";
}
return ms["value"];
case "select":
var end5 = html.IndexOf("</select>"u8, false, endIndex);
var optionHtml = html.Slice(endIndex + 1, end5 - endIndex - 1);
var selectedIndex = optionHtml.IndexOf(" selected"u8, true);// StringComparison.CurrentCultureIgnoreCase);
if (selectedIndex == -1)
{
selectedIndex = optionHtml.IndexOf("option"u8);
if (selectedIndex == -1)
{
return String.Empty;
}
}
int optionEndIndex;
var ov = FromValue(selectedIndex, optionHtml, out optionEndIndex);
if (ov.ContainsKey("value"))
{
return ov["value"];
}
else
{
if (html[endIndex - 1] == '/')
{
return String.Empty;
}
var end9 = optionHtml.IndexOf((byte)'<', optionEndIndex);
return optionHtml.Slice(optionEndIndex + 1, end9 - optionEndIndex - 1).UTF8();
}
case "textarea":
if (html[endIndex - 1] == '/')
{
return ms["value"] ?? String.Empty;
}
var end4 = html.IndexOf((byte)'<', endIndex);
if (end4 > 0)
{
return System.Web.HttpUtility.HtmlDecode(html.Slice(endIndex + 1, end4 - endIndex - 1).UTF8());
}
break;
}
return null;
}
public static string Expire(uint now, uint expireTime, string defaultStr)
{
var sExpireTime = defaultStr;// "未启用";
if (expireTime > 0)
{
if (expireTime == Int32.MaxValue)
{
sExpireTime = $"永不过期";
}
else if (expireTime > now)
{
var t = new TimeSpan(0, 0, (int)(expireTime - now)).TotalDays;
if (t < 0)
{
sExpireTime = $"还剩{t:0.0}天";
}
else
{
sExpireTime = $"还剩{t:0}天";
}
}
else
{
sExpireTime = "已过期";
}
}
return sExpireTime;
}
public static void Shared(int size, Action<byte[]> action)
{
var bufer = System.Buffers.ArrayPool<byte>.Shared.Rent(size);
try
{
action(bufer);
}
finally
{
System.Buffers.ArrayPool<byte>.Shared.Return(bufer);
}
}
static byte[] BuildDnsQuery(string domain)
{
var buffer = new byte[512];
var random = new Random();
ushort id = (ushort)random.Next(0, ushort.MaxValue);
// DNS Header
buffer[0] = (byte)(id >> 8);
buffer[1] = (byte)(id & 0xFF);
buffer[2] = 0x01; // recursion desired
buffer[3] = 0x00;
buffer[4] = 0x00; buffer[5] = 0x01; // QDCOUNT = 1
buffer[6] = 0x00; buffer[7] = 0x00; // ANCOUNT
buffer[8] = 0x00; buffer[9] = 0x00; // NSCOUNT
buffer[10] = 0x00; buffer[11] = 0x00; // ARCOUNT
// DNS Question
int pos = 12;
foreach (var part in domain.Split('.'))
{
buffer[pos++] = (byte)part.Length;
foreach (var c in System.Text.Encoding.ASCII.GetBytes(part))
buffer[pos++] = c;
}
buffer[pos++] = 0; // null terminator
buffer[pos++] = 0x00; buffer[pos++] = 0x01; // QTYPE = A
buffer[pos++] = 0x00; buffer[pos++] = 0x01; // QCLASS = IN
Array.Resize(ref buffer, pos);
return buffer;
}
public static ulong IPPort(UMC.Net.StringValue bytes)
{
if (bytes == null || bytes.Length == 0)
{
return 0;
}
else if (bytes.Length == 4)
{
var ip_port = new byte[8];
bytes.Span.CopyTo(ip_port.AsSpan(2));
ip_port[6] = 1;
ip_port[7] = 187;
return System.Buffers.Binary.BinaryPrimitives.ReadUInt64BigEndian(ip_port);
}
else if (bytes.Length < 8)
{
var k = new byte[8];
bytes.Span.CopyTo(k.AsSpan(8 - bytes.Length));
return System.Buffers.Binary.BinaryPrimitives.ReadUInt64BigEndian(k);
}
return System.Buffers.Binary.BinaryPrimitives.ReadUInt64BigEndian(bytes.Span);
}
public static async Task<IPAddress[]> GetHostAddresses(string domain, string dnsServer = "223.5.5.5")
{
byte[] query = BuildDnsQuery(domain);
byte[] response = await SendUdpQuery(dnsServer, 53, query);
return ParseDnsResponse(response);
}
private static async Task<byte[]> SendUdpQuery(string server, int port, byte[] query)
{
var client = new UdpClient();
await client.SendAsync(query, query.Length, server, port);
// var endpoint = new IPEndPoint(IPAddress.Any, 0);
client.Client.ReceiveTimeout = 3000;
var t = await client.ReceiveAsync();
return t.Buffer;
}
static IPAddress[] ParseDnsResponse(byte[] response)
{
if (response.Length < 12)
{
// Console.WriteLine("Invalid response");
return new IPAddress[0];
}
int qdcount = (response[4] << 8) | response[5];
int ancount = (response[6] << 8) | response[7];
int pos = 12;
// Skip question section
for (int i = 0; i < qdcount; i++)
{
while (response[pos] != 0) pos += response[pos] + 1;
pos += 5; // null + QTYPE + QCLASS
}
var adds = new List<IPAddress>();
for (int i = 0; i < ancount; i++)
{
if (pos + 12 > response.Length) break;
// Skip name (pointer or label)
if ((response[pos] & 0xC0) == 0xC0) pos += 2;
else
{
while (response[pos] != 0) pos += response[pos] + 1;
pos++;
}
ushort type = (ushort)((response[pos] << 8) | response[pos + 1]);
pos += 8; // type(2) + class(2) + TTL(4)
ushort rdlength = (ushort)((response[pos] << 8) | response[pos + 1]);
pos += 2;
if (type == 1 && rdlength == 4) // A record
{
adds.Add(new IPAddress(response.AsSpan(pos, 4)));
// Console.WriteLine($"A Record: {response[pos]}.{response[pos + 1]}.{response[pos + 2]}.{response[pos + 3]}");
}
pos += rdlength;
}
return adds.ToArray();
}
public static NetworkStream LocalItmeServier()
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPAddress(new byte[] { 127, 0, 0, 1 }), 443);
return new NetworkStream(socket, true);
}
public static Dictionary<string, object> DecodeToDictionary(ReadOnlyMemory<byte> data)
{
var reader = new CborReader(data, CborConformanceMode.Lax);
var result = ReadValue(ref reader) as Dictionary<string, object>;
return result!;
}
private static object ReadValue(ref CborReader reader)
{
switch (reader.PeekState())
{
case CborReaderState.StartMap:
return ReadMap(ref reader);
case CborReaderState.StartArray:
return ReadArray(ref reader);
case CborReaderState.TextString:
return reader.ReadTextString();
case CborReaderState.ByteString:
return reader.ReadByteString();
case CborReaderState.UnsignedInteger:
return reader.ReadUInt64();
case CborReaderState.NegativeInteger:
return reader.ReadInt64();
case CborReaderState.Boolean:
return reader.ReadBoolean();
case CborReaderState.Null:
reader.ReadNull();
return null;
default:
throw new NotSupportedException($"Unsupported CBOR type: {reader.PeekState()}");
}
}
private static Dictionary<string, object> ReadMap(ref CborReader reader)
{
int length = reader.ReadStartMap() ?? -1;
var dict = new Dictionary<string, object>();
if (length < 0)
{
// 不定长 Map
while (reader.PeekState() != CborReaderState.EndMap)
{
var key = ReadValue(ref reader)?.ToString() ?? "";
var value = ReadValue(ref reader);
dict[key] = value!;
}
}
else
{
// 定长 Map
for (int i = 0; i < length; i++)
{
var key = ReadValue(ref reader)?.ToString() ?? "";
var value = ReadValue(ref reader);
dict[key] = value!;
}
}
reader.ReadEndMap();
return dict;
}
private static object[] ReadArray(ref CborReader reader)
{
int length = reader.ReadStartArray() ?? -1;
var list = new List<object>();
if (length < 0)
{
// 不定长 array
while (reader.PeekState() != CborReaderState.EndArray)
{
list.Add(ReadValue(ref reader));
}
}
else
{
// 定长 array
for (int i = 0; i < length; i++)
{
list.Add(ReadValue(ref reader));
}
}
reader.ReadEndArray();
return list.ToArray();
}
public static void SyncClient(byte type, params StringValue[] stringValues)
{
SyncClient((s, v) => { }, type, stringValues);
}
public static void SyncClient(Action<System.IO.Stream, byte[]> action, byte type, params StringValue[] stringValues)
{
Utility.Shared(8192, buffer =>
{
try
{
var t = Utility.TimeSpan().StringValue();
t.Span.Reverse();
t.Span.CopyTo(buffer);
WebServlet.AppId.Span.CopyTo(buffer.AsSpan(4));
WebServlet.AppSecret.Span.CopyTo(buffer.AsSpan(20));
Utility.MD5(buffer.AsSpan(0, 36), buffer.AsSpan(9));
t.Span.CopyTo(buffer.AsSpan(5));
buffer[0] = 0x16;
buffer[1] = 0x00;
buffer[2] = 0x07;
buffer[3] = type;
buffer[4] = 20;
int index = 25;
var longString = StringValue.Empty;
foreach (var item in stringValues)
{
if (item.Length > byte.MaxValue)
{
buffer[index] = 3;
index++;
buffer[index] = 0;
index++;
ushort len = (ushort)item.Length;
buffer[index] = (byte)(len >> 8);
index++;
buffer[index] = (byte)(len & 0xFF);
index++;
longString = item;
break;
}
else
{
buffer[index] = (byte)item.Length;
item.Span.CopyTo(buffer.AsSpan(index + 1));
index += buffer[index] + 1;
}
}
buffer[index] = 0x00;
index++;
using (var stream = Utility.LocalItmeServier())
{
stream.Write(buffer, 0, index);
if (longString.Length > 0)
{
stream.Write(longString.Span);
}
action(stream, buffer);
stream.Close();
stream.Dispose();
}
}
catch //(Exception e)
{
// Utility.Error("SyncClient", DateTime.Now, e);
}
});
}
public static void Certificate(NetHttpResponse r)
{
if (r.StatusCode == System.Net.HttpStatusCode.OK)
{
r.ReadAsString(str =>
{
var cert = JSON.Deserialize<WebMeta>(str);
if (cert.ContainsKey("privateKey"))
{
var domain = cert["domain"];
var privateKey = cert["privateKey"];
var publicKey = cert["publicKey"];
var x509 = X509Certificate2.CreateFromPem(publicKey, privateKey);
Certificater.Certificates[domain] = new Certificater(domain, x509);
HotCache.Put(new Entities.SiteCert
{
Domain = new StringValue(domain),
ExpirationTime = Utility.TimeSpan(x509.NotAfter),
CheckTime = Utility.TimeSpan(),
PrivateKey = new StringValue(privateKey),
PublicKey = new StringValue(publicKey),
IsApiumc = false
});
}
});
}
else
{
r.ReadAsString(x => { });
}
}
public static Web.WebMeta FromValue(Span<byte> html, bool isKey)
{
var webMeta = new System.Collections.Generic.Dictionary<String, List<String>>();
var nKey = " name="u8;
int index = html.IndexOf(nKey);
while (index > 0)
{
var startIndex = index + nKey.Length;
var start = html[startIndex];
switch (start)
{
case 34:
case 39:
// case (byte)'\'':
// case (byte)'"':
var endIndex = html.IndexOf(start, startIndex + 1);
if (endIndex > startIndex)
{
var name = html.Slice(startIndex + 1, endIndex - startIndex - 1).UTF8();
var value = FromValue(html, index, !isKey, out endIndex);
if (value != null)
{
List<String> vs;
if (webMeta.TryGetValue(name, out vs))
{
vs.Add(value);
}
else
{
vs = new List<string>
{
value
};
webMeta[name] = vs;
}
startIndex = endIndex;
}
else
{
startIndex = endIndex;
}
}
break;
}
index = html.IndexOf(nKey, false, startIndex);
}
var meta = new Web.WebMeta();
var em = webMeta.GetEnumerator();
while (em.MoveNext())
{
meta.Put(em.Current.Key, String.Join(",", em.Current.Value.ToArray()));
}
return meta;
}
public static NetHttpRequest Sign(NetHttpRequest http, String secret)
{
http.Add(new HeadValue("umc-app-version", APIProxy.Version));
http.Add(new HeadValue("umc-proxy-sites", HotCache.Caches().First(r => r.Name == "Site").Count.ToString()));
http.Add(new HeadValue("umc-proxy-session", HotCache.Caches().First(r => r.Name == "Session").Count.ToString()));
http.Add(new HeadValue("umc-client-pfm", "sync"));
http.Add(new HeadValue("umc-request-time", UMC.Data.Utility.TimeSpan().ToString()));
if (String.IsNullOrEmpty(secret) == false)
{
http.Add("umc-request-sign", UMC.Data.Utility.Sign(http.Headers, "umc-"u8, secret));
}
return http;
}
public static int Random(StringValue val)
{
var fs = val.Span;
if (fs.Length >= 4)
{
int v = BitConverter.ToInt32(fs);
for (var i = 4; i < fs.Length; i++)
{
v = v ^ fs[i];
}
return v;
}
else
{
var b = new byte[4];
fs.CopyTo(b.AsSpan(4 - fs.Length));
return BitConverter.ToInt32(b);
}
}
public static int Random(string val)
{
if (String.IsNullOrEmpty(val) == false)
{
var fs = System.Text.Encoding.UTF8.GetBytes(val);
if (fs.Length >= 4)
{
int v = BitConverter.ToInt32(fs);
for (var i = 4; i < fs.Length; i++)
{
v = v ^ fs[i];
}
return v;
}
else
{
var b = new byte[4];
Array.Copy(fs, 0, b, 4 - fs.Length, fs.Length);
return BitConverter.ToInt32(b);
}
}
return 0;
}
public static string FirstReplace(string val, string s, string t)
{
var index = val.IndexOf(s);
if (index == -1)
{
return val;
}
else
{
return $"{val.Substring(0, index)}{t}{val.Substring(index + s.Length)}";
}
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C#
1
https://gitee.com/apiumc/WebVPN.git
git@gitee.com:apiumc/WebVPN.git
apiumc
WebVPN
WebVPN
master

搜索帮助