Beispiel #1
0
        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
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
 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);
             }
         }
     }
 }
Beispiel #4
0
        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,
            }));
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
 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);
     }
 }
Beispiel #7
0
        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);
                    }
                }
Beispiel #8
0
 protected virtual void PrivateInput(SkylakeNATClient socket, IPFrame packet)
 {
     this.NAT.PrivateInput(packet);
 }
Beispiel #9
0
 protected virtual void ProcessAbort(SkylakeNATClient socket)
 {
     this.NAT.Release(socket.Address);
 }
Beispiel #10
0
        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
        }