protected virtual void ProcessAuthentication(SkylakeNATClient socket) { IPAddress localIP = this.AddressAllocation(socket.Id); if (localIP == null) { socket.Close(); } else { if (this.ResponseAuthentication(socket, localIP, this._dhcpServerAddress, this._dnsServerAddress)) { lock (this._sockets) { if (!_sockets.TryGetValue(socket.Address, out LinkedList <SkylakeNATClient> s) || s == null) { s = new LinkedList <SkylakeNATClient>(); _sockets[socket.Address] = s; #if __USE_UDP_PAYLOAD_TAP_PACKET s.AddLast(socket); #endif } #if !__USE_UDP_PAYLOAD_TAP_PACKET if (s != null) { socket._rsv_current = s.AddLast(socket); } #endif } } #if __USE_UDP_PAYLOAD_TAP_PACKET Console.WriteLine($"[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}] {socket.Id} {socket.Address} {socket.LocalEndPoint}"); #endif } }
protected virtual bool Send(IPAddress address, Func <SkylakeNATMessage> message, int sent = 1) { if (address == null || message == null) { return(false); } SkylakeNATClient socket = this.GetClient(address, out int sessions); if (socket == null) { return(false); } SkylakeNATMessage packet = message(); if (!socket.Send(packet, sent)) { for (int i = 0; i < sessions; i++) { socket = this.GetClient(address, out sessions); if (socket == null) { break; } if (socket.Send(packet, sent)) { return(true); } } } return(false); }
protected virtual void ProcessMessage(SkylakeNATClient socket, SkylakeNATMessage message) { if (message.Commands == Commands.NATCommands_kEthernetOutput) { IPFrame packet = IPv4Layer.ParseFrame(message.Payload, false); if (packet != null) { if (this._sockets.ContainsKey(packet.Source)) { this.PrivateInput(socket, packet); } else { this.CloseManyClient(socket.Address); } } } }
protected virtual bool ResponseAuthentication(SkylakeNATClient socket, IPAddress local, IPAddress dhcp, IPAddress dns) { byte[] message = new byte[sizeof(NATAuthenticationResponse)]; fixed(byte *pinned = message) { NATAuthenticationResponse *response = (NATAuthenticationResponse *)pinned; response->dhcp.local = (uint)Ethernet.GetAddress(local); response->dhcp.dhcp = (uint)Ethernet.GetAddress(dhcp); response->dhcp.dns = (uint)Ethernet.GetAddress(dns); } socket.Address = local; return(socket.Send(new SkylakeNATMessage(new BufferSegment(message)) { Commands = Commands.NATCommands_kAuthentication, })); }
protected virtual SkylakeNATClient GetClient(IPAddress address, out int sessions) { sessions = 0; SkylakeNATClient socket = null; lock (this._sockets) { if (_sockets.TryGetValue(address, out LinkedList <SkylakeNATClient> s) && s != null) { var node = s.First; s.RemoveFirst(); s.AddLast(node); socket = node.Value; sessions = s.Count; } } return(socket); }
protected virtual bool CloseManyClient(IPAddress address) { if (address == null) { return(false); } lock (this._sockets) { _sockets.TryRemove(address, out LinkedList <SkylakeNATClient> s); if (s == null) { return(false); } var node = s.First; SkylakeNATClient socket = null; while (node != null) { var i = node.Value; if (i != null) { socket = i; i.Close(); } node = node.Next; } if (socket != null) { lock (_addressAllocation) { _addressAllocation.TryRemove(socket.Id, out IPAddress address_x); if (socket.Address != null) { _assignedAddresses.Remove(socket.Address); } else if (address_x != null) { _assignedAddresses.Remove(address_x); } } } return(true); } }
private void ProcessReceiveFromUdp(IAsyncResult ar) { lock (this._syncobj) { try { if (this._disposed) return; } if (ar == null) { EndPoint remoteEP = this._server.LocalEndPoint; this._server.BeginReceiveFrom(_mssPacketBuffer, 0, _mssPacketBuffer.Length, 0, ref remoteEP, ProcessReceiveFromUdp, null); } else { EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); int bytes = this._server.EndReceiveFrom(ar, ref remoteEP); do { if (bytes < sizeof(pkg_hdr)) break; fixed(byte *pinned = _mssPacketBuffer) { pkg_hdr *pkg = (pkg_hdr *)pinned; if (pkg->fk != pkg_hdr.FK) { break; } if ((pkg->len + sizeof(pkg_hdr)) != bytes) { break; } if (pkg->id == 0) { break; } Commands commands = unchecked ((Commands)pkg->cmd); if (commands == Commands.NATCommands_kAuthentication) { NATClientContext context = null; SkylakeNATClient client = null; lock (this._sockets) { if (!_natClientTable.TryGetValue(pkg->id, out context) || context == null) { client = this.CreateClient(pkg->id, remoteEP); if (client != null) { client.LocalEndPoint = remoteEP; context = new NATClientContext() { client = client }; _natClientTable[pkg->id] = context; client.Abort += this._onSocketAbort; client.Message += this._onSocketMessage; client.Authentication += this._onAuthentication; } } else { client = context.client; } } if (context != null && client != null) { lock (context) { context.agingsw.Restart(); } client.LocalEndPoint = remoteEP; client.OnAuthentication(EventArgs.Empty); } } else { SkylakeNATClient client = null; lock (this._sockets) { _natClientTable.TryGetValue(pkg->id, out NATClientContext context); if (context != null) { lock (context) { context.agingsw.Restart(); } client = context.client; } } if (client != null) { BufferSegment payload = null; if (pkg->len > 0) { int ofs = sizeof(pkg_hdr); #if _USE_RC4_SIMPLE_ENCIPHER fixed(byte *payloadPtr = &_mssPacketBuffer[ofs]) RC4.rc4_crypt(this.Key, payloadPtr, pkg->len, this.Subtract, 0); #endif payload = client._encryptor.Decrypt(new BufferSegment(_mssPacketBuffer, ofs, pkg->len)); } else { payload = new BufferSegment(BufferSegment.Empty); } client.OnMessage(new SkylakeNATMessage(payload) { Commands = commands, }); } } } } while (false); this.ProcessReceiveFromUdp(null); } }
protected virtual void PrivateInput(SkylakeNATClient socket, IPFrame packet) { this.NAT.PrivateInput(packet); }
protected virtual void ProcessAbort(SkylakeNATClient socket) { this.NAT.Release(socket.Address); }
public Router(IPAddress ethernet, int port, string key, int subtract) { if (ethernet == null) { throw new ArgumentNullException("It is not allowed to specify an ethernet card address with a null value"); } if (IPEndPoint.MinPort >= port || port > IPEndPoint.MaxPort) { throw new ArgumentOutOfRangeException($"The port used to connect to the server is less than or equal to {IPEndPoint.MinPort} or greater than {IPEndPoint.MaxPort}"); } this.Port = port; this.Key = key; this.Subtract = subtract; #if !__USE_UDP_PAYLOAD_TAP_PACKET this._server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._server.NoDelay = true; this._server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); #else this._server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); this._server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); #endif this._server.Bind(new IPEndPoint(ethernet, port)); this._onSocketAbort = (sender, e) => { if (sender is SkylakeNATClient socket) { socket.Close(); if (socket.Address != null) { lock (this._sockets) { bool deleteCompletely = false; if (_sockets.TryGetValue(socket.Address, out LinkedList <SkylakeNATClient> s)) { if (s == null) { deleteCompletely = true; } else { var node = socket._rsv_current; if (node != null) { var l = node.List; if (l != null) { l.Remove(node); } socket._rsv_current = null; } if (s.Count <= 0) { deleteCompletely = true; } } } if (deleteCompletely) { _sockets.TryRemove(socket.Address, out s); lock (_addressAllocation) { _addressAllocation.TryRemove(socket.Id, out IPAddress address_x); if (socket.Address != null) { _assignedAddresses.Remove(socket.Address); } else if (address_x != null) { _assignedAddresses.Remove(address_x); } } } } this.ProcessAbort(socket); } } }; this._onSocketMessage = (sender, e) => { if (sender is SkylakeNATClient socket) { this.ProcessMessage(socket, e); } }; this._onAuthentication = (sender, e) => { if (sender is SkylakeNATClient socket) { this.ProcessAuthentication(socket); } }; // 建立以太网NAT链路工作引擎 #if NO_USAGE_PCAP_NET this.Ethernet = new Ethernet(ethernet, false); #else this.Ethernet = new Ethernet(ethernet, true); #endif this.NAT = new NAT(this.Ethernet.GetEthernetAddress()); // 建立以太网NAT传入传出链路 this.NAT.PublicOutput += (sender, e) => this.Ethernet.Output(e); this.NAT.PrivateOutput += (seder, e) => this.PrivateOutput(e); this.Ethernet.PublicInput += (sender, e) => this.NAT.PublicInput(e); #if __USE_UDP_PAYLOAD_TAP_PACKET this._doAgingswNatClientContextTimer = new Timer(); this._doAgingswNatClientContextTimer.Elapsed += (sender, e) => { foreach (var kv in _natClientTable) { bool freely = false; var context = kv.Value; if (context == null) { freely = true; } else { SkylakeNATClient clients = null; lock (context) { if (context.agingsw.ElapsedMilliseconds >= 10000) { freely = true; clients = context.client; } } clients?.OnAbort(EventArgs.Empty); } if (freely) { lock (this._sockets) { SkylakeNATClient clients = context.client; if (clients != null) { IPAddress address = IPAddress.Any; lock (_addressAllocation) { _addressAllocation.TryRemove(clients.Id, out address); if (address == null) { address = clients.Address; } if (address != null && !Ethernet.Equals(address, IPAddress.Any)) { _assignedAddresses.Remove(address); _sockets.TryRemove(address, out LinkedList <SkylakeNATClient> linkedlist_xx); } } } _natClientTable.TryRemove(kv.Key, out NATClientContext context_xx); } } } }; this._doAgingswNatClientContextTimer.Interval = 500; this._doAgingswNatClientContextTimer.Start(); #endif }