private void initKey(string method, string password) { cipher = Cipher.CreateByName(method); if (cipher == null) { throw new ArgumentOutOfRangeException("Such encryption cipher methods are not supported"); } byte[] passbuf = Encoding.Default.GetBytes(password); key = new byte[cipher.KeyLength]; iv = new byte[cipher.IVLength]; if (Native.EVP_BytesToKey(cipher.Handle, MessageDigest.MD5.Handle, null, passbuf, passbuf.Length, 1, key, iv) <= 0) { throw new ExternalException("Bytes to key calculations cannot be performed using cipher with md5(md) key password iv key etc"); } int ivLen = cipher.IVLength; int md5len = ivLen < sizeof(Guid) ? sizeof(Guid) : ivLen; iv = new byte[ivLen]; // RAND_bytes(iv.get(), ivLen); = new byte[ivLen]; // RAND_bytes(iv.get(), ivLen); // MD5->RC4 Buffer.BlockCopy(HashAlgorithm <MD5> . ComputeHash( merges( Encoding.Default.GetBytes($"SkylakeNAT@{method}."), key, Encoding.Default.GetBytes($".{password}"))), 0, iv, 0, sizeof(Guid)); fixed(byte *piv = iv) fixed(byte *pkey = key) RC4.rc4_crypt(pkey, cipher.KeyLength, piv, ivLen, 0, 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); } }
public virtual bool Send(SkylakeNATMessage message, int sent = 1) { if (message == null) { return(false); } Socket socket = null; lock (this._syncobj) { socket = this._socket; if (socket == null) { return(false); } } BufferSegment payload_segment = message.Payload; #if !_USE_RC4_SIMPLE_ENCIPHER || __USE_UDP_PAYLOAD_TAP_PACKET if (payload_segment.Length > 0) { payload_segment = this._encryptor.Encrypt(payload_segment); } #endif int payload_size = payload_segment.Length; byte[] packet = new byte[sizeof(pkg_hdr) + payload_size]; fixed(byte *pinned = packet) { pkg_hdr *pkg = (pkg_hdr *)pinned; pkg->fk = pkg_hdr.FK; pkg->len = unchecked ((ushort)payload_size); pkg->cmd = unchecked ((byte)message.Commands); if (payload_size > 0) { byte *payload_data = sizeof(pkg_hdr) + pinned; Marshal.Copy(payload_segment.Buffer, payload_segment.Offset, (IntPtr)payload_data, payload_size); #if _USE_RC4_SIMPLE_ENCIPHER RC4.rc4_crypt(this.Router.Key, payload_data, payload_size, this.Router.Subtract, 1); #endif } } #if _USE_RC4_SIMPLE_ENCIPHER try { if (sent <= 0) { sent = 1; } for (int i = 0; i < sent; i++) { socket.BeginSendTo(packet, 0, packet.Length, SocketFlags.None, this.LocalEndPoint, (ar) => { try { socket.EndSendTo(ar); } catch (Exception) { } }, null); } return(true); } catch (Exception) { return(false); } #else SocketError error = SocketError.SocketError; try { socket.BeginSend(packet, 0, packet.Length, SocketFlags.None, out error, (ar) => { error = SocketError.SocketError; try { socket.EndSend(ar, out error); } catch (Exception) { error = SocketError.SocketError; } if (error != SocketError.Success) { this.CloseOrAbort(); } }, null); } catch (Exception) { error = SocketError.SocketError; } if (error != SocketError.Success && error != SocketError.IOPending) { this.CloseOrAbort(); return(false); } return(true); #endif }
private void StartReceive(IAsyncResult ar) { SkylakeNATMessage message = null; SocketError error = SocketError.SocketError; try { do { Socket socket = null; lock (this._syncobj) socket = this._socket; if (socket == null) { return; } if (ar == null) { if (!_fhdr) { socket.BeginReceive(_phdr, 0, _phdr.Length, SocketFlags.None, out error, StartReceive, null); } else { int suplus = _message.Length - _fseek; if (suplus >= Layer3Netif.MSS) { suplus = Layer3Netif.MSS; } socket.BeginReceive(_message, _fseek, suplus, SocketFlags.None, out error, StartReceive, null); } if (error == SocketError.IOPending) { error = SocketError.Success; } } else { int len = -1; try { len = socket.EndReceive(ar, out error); } catch (Exception) { len = -1; } if (len <= 0) { error = SocketError.SocketError; break; } else { bool completion = false; if (!_fhdr) { fixed(byte *pinned = _phdr) { pkg_hdr *pkg = (pkg_hdr *)pinned; if (len != sizeof(pkg_hdr) || pkg->fk != pkg_hdr.FK) { error = SocketError.SocketError; break; } if (0 == pkg->len) { completion = true; } else { _fseek = 0; _fhdr = true; _message = new byte[pkg->len]; } error = SocketError.Success; } } else { _fseek += len; if (_fseek >= _message.Length) { completion = true; } error = SocketError.Success; } if (completion) { fixed(byte *pinned = _phdr) { pkg_hdr *pkg = (pkg_hdr *)pinned; if (0 == pkg->len) { message = new SkylakeNATMessage(new BufferSegment(BufferSegment.Empty)); } else { message = new SkylakeNATMessage(new BufferSegment(_message)); } if (0 == this.Id) { this.Id = pkg->id; } message.Commands = unchecked ((Commands)pkg->cmd); _fseek = 0; _fhdr = false; _message = null; } error = SocketError.Success; } } } } while (false); } catch (Exception) { error = SocketError.SocketError; } if (error != SocketError.Success) { this.CloseOrAbort(); } else if (ar != null) { if (message != null) { BufferSegment segment = message.Payload; #if !_USE_RC4_SIMPLE_ENCIPHER if (segment.Length > 0) { segment = this._encryptor.Decrypt(segment); message.Payload = segment; } #else fixed(byte *pinned = segment.Buffer) if (pinned != null) { RC4.rc4_crypt(this.Router.Key, pinned, segment.Length, this.Router.Subtract, 0); } #endif if (message.Commands != Commands.NATCommands_kAuthentication) { this.OnMessage(message); } else { this.OnAuthentication(message); } } this.StartReceive(null); } }