public void Bind( IPEndPoint endPoint ) { if( fAcceptSocket != null ) { throw new InvalidOperationException( "Socket is already bound" ); } fAcceptSocket = new SecureSocket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, fOptions ); fAcceptSocket.Bind( endPoint ); fAcceptSocket.Listen( 10 ); }
///<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>Starts listening on the selected IP address and port.</summary> ///<exception cref="SocketException">There was an error while creating the listening socket.</exception> public void Start() { try { ListenSocket = new SecureSocket(Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); ListenSocket.Bind(new IPEndPoint(Address, Port)); ListenSocket.Listen(50); ListenSocket.BeginAccept(new AsyncCallback(this.OnAccept), ListenSocket); } catch { ListenSocket = null; throw new SocketException(); } }
/// <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..."); } }
///<summary>Processes a received query.</summary> ///<param name="Query">The query to process.</param> private void ProcessQuery(byte [] Query) { try { switch(Query[1]) { case 1: //CONNECT IPAddress RemoteIP = null; int RemotePort = 0; if (Query[3] == 1) { RemoteIP = IPAddress.Parse(Query[4].ToString() + "." + Query[5].ToString() + "." + Query[6].ToString() + "." + Query[7].ToString()); RemotePort = Query[8] * 256 + Query[9]; } else if( Query[3] == 3) { RemoteIP = Dns.Resolve(Encoding.ASCII.GetString(Query, 5, Query[4])).AddressList[0]; RemotePort = Query[4] + 5; RemotePort = Query[RemotePort] * 256 + Query[RemotePort + 1]; } RemoteConnection = new SecureSocket(RemoteIP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); RemoteConnection.BeginConnect(new IPEndPoint(RemoteIP, RemotePort), new AsyncCallback(this.OnConnected), RemoteConnection); break; case 2: //BIND byte [] Reply = new byte[10]; 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); Reply[0] = 5; //Version 5 Reply[1] = 0; //Everything is ok :) Reply[2] = 0; //Reserved Reply[3] = 1; //We're going to send a IPv4 address 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 Reply[8] = (byte)(Math.Floor(((IPEndPoint)AcceptSocket.LocalEndPoint).Port / 256)); //Port/1 Reply[9] = (byte)(((IPEndPoint)AcceptSocket.LocalEndPoint).Port % 256); //Port/2 Connection.BeginSend(Reply, 0, Reply.Length, SocketFlags.None, new AsyncCallback(this.OnStartAccept), Connection); break; case 3: //ASSOCIATE //ASSOCIATE is not implemented (yet?) Dispose(7); break; default: Dispose(7); break; } } catch { Dispose(1); } }
///<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>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); } }