///<summary>Called when we're connected to the data port of the remote FTP server.</summary> ///<param name="ar">The result of the asynchronous operation.</param> private void OnPasvConnected(IAsyncResult ar) { try { DestinationSocket.EndConnect(ar); ListenSocket = new SecureSocket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ListenSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); ListenSocket.Listen(1); ListenSocket.BeginAccept(new AsyncCallback(this.OnPasvAccept), ListenSocket); Parent.SendCommand("227 Entering Passive Mode (" + Listener.GetLocalInternalIP().ToString().Replace('.', ',') + "," + Math.Floor(((IPEndPoint)ListenSocket.LocalEndPoint).Port / 256).ToString() + "," + (((IPEndPoint)ListenSocket.LocalEndPoint).Port % 256).ToString() + ").\r\n"); } catch { Dispose(); } }
///<summary>Initializes a new instance of the FtpDataConnection class.</summary> ///<param name="RemoteAddress">The address on the local FTP client to connect to.</param> ///<returns>The PORT command string to send to the FTP server.</returns> public string ProcessPort(IPEndPoint RemoteAddress) { try { ListenSocket = new SecureSocket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ListenSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); ListenSocket.Listen(1); ListenSocket.BeginAccept(new AsyncCallback(this.OnPortAccept), ListenSocket); ClientSocket = new SecureSocket(RemoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ClientSocket.BeginConnect(RemoteAddress, new AsyncCallback(this.OnPortConnected), ClientSocket); return("PORT " + Listener.GetLocalExternalIP().ToString().Replace('.', ',') + "," + Math.Floor(((IPEndPoint)ListenSocket.LocalEndPoint).Port / 256).ToString() + "," + (((IPEndPoint)ListenSocket.LocalEndPoint).Port % 256).ToString() + "\r\n"); } catch { Dispose(); return("PORT 0,0,0,0,0,0\r\n"); } }
///<summary>Processes a SOCKS request from a client.</summary> ///<param name="Request">The request to process.</param> protected override void ProcessRequest(byte [] Request) { int Ret; try { if (Request[0] == 1) // CONNECT { IPAddress RemoteIP; int RemotePort = Request[1] * 256 + Request[2]; Ret = Array.IndexOf(Request, (byte)0, 7); Username = Encoding.ASCII.GetString(Request, 7, Ret - 7); if (Request[3] == 0 && Request[4] == 0 && Request[5] == 0 && Request[6] != 0) // Use remote DNS { Ret = Array.IndexOf(Request, (byte)0, Ret + 1); RemoteIP = Dns.Resolve(Encoding.ASCII.GetString(Request, Username.Length + 8, Ret - Username.Length - 8)).AddressList[0]; } else //Do not use remote DNS { RemoteIP = IPAddress.Parse(Request[3].ToString() + "." + Request[4].ToString() + "." + Request[5].ToString() + "." + Request[6].ToString()); } RemoteConnection = new SecureSocket(RemoteIP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); RemoteConnection.BeginConnect(new IPEndPoint(RemoteIP, RemotePort), new AsyncCallback(this.OnConnected), RemoteConnection); } else if (Request[0] == 2) // BIND { byte [] Reply = new byte[8]; long LocalIP = Listener.GetLocalExternalIP().Address; AcceptSocket = new SecureSocket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp); AcceptSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); AcceptSocket.Listen(50); RemoteBindIP = IPAddress.Parse(Request[3].ToString() + "." + Request[4].ToString() + "." + Request[5].ToString() + "." + Request[6].ToString()); Reply[0] = 0; //Reply version 0 Reply[1] = 90; //Everything is ok :) Reply[2] = (byte)(Math.Floor(((IPEndPoint)AcceptSocket.LocalEndPoint).Port / 256)); //Port/1 Reply[3] = (byte)(((IPEndPoint)AcceptSocket.LocalEndPoint).Port % 256); //Port/2 Reply[4] = (byte)(Math.Floor((LocalIP % 256))); //IP Address/1 Reply[5] = (byte)(Math.Floor((LocalIP % 65536) / 256)); //IP Address/2 Reply[6] = (byte)(Math.Floor((LocalIP % 16777216) / 65536)); //IP Address/3 Reply[7] = (byte)(Math.Floor(LocalIP / 16777216)); //IP Address/4 Connection.BeginSend(Reply, 0, Reply.Length, SocketFlags.None, new AsyncCallback(this.OnStartAccept), Connection); } } catch { Dispose(91); } }
/// <summary> /// Starts listening for incoming server connections. /// </summary> /// <param name="ep">The EndPoint on which to listen.</param> /// <param name="sp">The protocol to use.</param> /// <param name="pfxfile">An optional PFX file.</param> /// <param name="password">An optional PFX password.</param> public void StartServer(IPEndPoint ep, SecureProtocol sp, Certificate cert) { // initialize a SecurityOptions instance SecurityOptions options = new SecurityOptions(sp, cert, ConnectionEnd.Server); // create a new SecureSocket with the above security options SecureSocket s = new SecureSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, options); // from here on, act as if the SecureSocket is a normal Socket s.Bind(ep); s.Listen(10); Console.WriteLine("Listening on " + s.LocalEndPoint.ToString()); SecureSocket ss; string query = ""; byte[] buffer = new byte[1024]; int ret; while (true) { ss = (SecureSocket)s.Accept(); Console.WriteLine("Incoming socket accepted."); // receive HTTP query Console.WriteLine("Receiving HTTP request..."); ret = 0; query = ""; while (!IsComplete(query)) // wait until we've received the entire HTTP query { try { ret = ss.Receive(buffer, 0, buffer.Length, SocketFlags.None); } catch (Exception e) { Console.WriteLine("Error while receiving data from client [" + e.Message + "]."); Console.WriteLine(e); break; } if (ret == 0) { Console.WriteLine("Client closed connection too soon."); ss.Close(); break; } query += Encoding.ASCII.GetString(buffer, 0, ret); } if (IsComplete(query)) { // Send HTTP reply Console.WriteLine("Sending reply..."); ret = 0; try { while (ret != MentalisPage.Length) { ret += ss.Send(Encoding.ASCII.GetBytes(MentalisPage), ret, MentalisPage.Length - ret, SocketFlags.None); } ss.Shutdown(SocketShutdown.Both); ss.Close(); } catch (Exception e) { Console.WriteLine("Error while sending data to the client [" + e.Message + "]."); Console.WriteLine(e); } } Console.WriteLine("Waiting for another connection..."); } }