title: Python socket.accept() not receiving any connection requests
body: <p>I recently bought the book <em>Black Hat Python</em> by Justin Seitz because I've been interested in getting into Python and playing around with network security.</p>
  
  <p>I'm working in <em><strong>Kali Linux</strong></em> and one of the examples in the book is a simple TCP Proxy. I've already written a few scripts that are connected through ports, but now I'm having trouble trying to create a connection to a remote server, such as Google.</p>
  
  <p>Now, I admit that I'm just about a complete novice with Python. I mostly program in C++. As a disclosure, I did move the main() function to the top of the code as to be organized in order of execution. In the actual source, it's located at the very bottom.</p>
  
  <pre><code>import sys
  import socket
  import threading
  import time
  import os
  
  def main():
      if len(sys.argv[1:]) != 5:
          print "Usage: nproxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]"
          print "Example: nproxy.py 127.0.0.1 5555 ftp.example.com 5555 True"
          sys.exit(0)
  
      #setup listening parameters
      local_host = sys.argv[1]
      local_port = sys.argv[2]
      #setup remote target
      remote_host = sys.argv[3]
      remote_port = sys.argv[4]
      #this tells our proxy to connect and receive data before sending to the remote host
      receive_first = sys.argv[5]
  
      if "True" in receive_first:
          receive_first = True
      else:
          receive_first = False
  </code></pre>
  
  <p>Everything from here up is just the main() function getting all of the parameters and variables parsed and setup.</p>
  
  <pre><code>    #spin listening socket
      server_loop(local_host, local_port, remote_host, remote_port, receive_first)
  
  #status class for my timeout function to stop the socket.accept()
  class status:
      connected = False
  </code></pre>
  
  <p>The server_loop() function is the source function for my issue. It contains all of the code for connecting clients to the servers.</p>
  
  <p>The first section is just setting up my server socket as well as creating a few execution shortcuts for myself.</p>
  
  <pre><code>def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
      #setup server socket
      server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  
      if "@" in local_host:
          local_host = "127.0.0.1"
  
      if "@" in local_port:
          local_port = remote_port
  
      local_addr = (local_host, int(local_port))
      remote_addr = (remote_host, int(remote_port))
  </code></pre>
  
  <p>Binding the server to my local address works just fine. It's during the while loop that the problem starts, I would think.</p>
  
  <pre><code>    try:
          server.bind(local_addr)
      except:
          print "[!!] Failed to listen on %s:%d" % local_addr
          print "[!!] Check for other listening sockets or correct permissions."
          sys.exit(0)
  
      print "[*] Listening on %s:%d" % local_addr
      server.listen(5)
  </code></pre>
  
  <p>Here starts the while loop to keep the program open to handle incoming connections. The tout thread contains the code for timing out and closing the server socket.</p>
  
  <pre><code>    while True:
          tout = threading.Thread(target=timeout, args=(local_host, local_port))
          tout.start()
          print "[*] Connecting..."
  </code></pre>
  
  <p>This seems to be where my program hangs. You see, I'm not 100% sure how this is supposed to be handled. In the book, the code works just fine for him and will successfully return from server.accept() and connect the client_socket to the correct address.</p>
  
  <p>In my execution, however, the program stops at the accept() function and never returns any socket or address data. Unless my understanding of the accept() function is wrong and the code wasn't designed with remote servers in mind.</p>
  
  <p>I'm not entirely sure how the accept() function even works. Does it send a SYN packet to the host to initiate a connection request or is the function just sitting there waiting, thinking that the host is going to send a SYN-ACK return when no SYN was even sent in the first place?</p>
  
  <pre><code>        client_socket, addr = server.accept()
  
          #The timeout function is designed to close the server by feeding     
          #it the localhost address. If this happens, the statement below catches the 
          #program and calls that the server request has timed out.
  
          if "127.0.0.1" in addr[0]:
              print "[!!] Server connection has timed out."
              sys.exit(0)
          #print out the local connection information
          status.connected = True
          print "[==&gt;] Received incoming connection from %s:%d" % (addr[0], addr[1])
  
          #start a thread to talk to the remote host
  </code></pre>
  
  <p>If the server.accept() were to return normally, the client_socket would be connected to the host and initialize the rest of the proxy as it sends and receives data normally. The rest of the code is for completion in case I missed something crucial that's actually the cause of the failure.</p>
  
  <pre><code>        proxy_thread = threading.Thread(target=proxy_handler, args=(client_socket, remote_addr, receive_first))
          proxy_thread.start()
  
  def timeout(local_host, local_port):
      t = 5
      while True:
          if status.connected is True:
              break
          if t &lt;= 0:
              wake = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
              wake.connect((local_host, int(local_port)))
              break
          time.sleep(0.1)
          t-=0.1
  
  
  def proxy_handler(client_socket, remote_host, remote_port, receive_first):
      #connect to the remote host
      remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      remote_socket.connect(remote_addr)
  
      if receive_first:
          remote_buffer = receive_from(remote_socket)
          hexdump(remote_buffer)
  
          #send it to our response handler
          remote_buffer = response_handler(remote_buffer)
  
          #if we have data to send to our local client, send it
          if len(remote_buffer):
              print "[&lt;==] Sending %d bytes to localhost." % len(remote_buffer)
              client_socket.send(remote_buffer)
  
      #now let's loop and read from local
      #send to remote, send to local
      #rinse and repeat
      while True:
          #read from localhost
          local_buffer = receive_from(client_socket)
          if len(local_buffer):
              print "[==&gt;] Received %d bytes from localhost." % len(local_buffer)
              hexdump(local_buffer)
  
              #send it to our request handler
              local_buffer = request_handler(local_buffer)
  
              #send off the data to the remote host
              remote_socket.send(local_buffer)
              print "[==&gt;] Sent to remote."
  
          #receive back a response
          remote_buffer = receive_from(remote_socket)
  
          if len(remote_buffer):
              print "[&lt;==] Received %d bytes from remote" % len(remote_buffer)
              hexdump(remote_buffer)
  
              #send to our response handler
              remote_buffer = response_handler(remote_buffer)
  
              #send the response to the local socket
              client_socket.send(remote_buffer)
              print "[&lt;==] Sent to localhost."
  
          #if no more data on either side, close the connection
          if not len(local_buffer) or not len(remote_buffer):
              client_socket.close()
              remote_socket.close()
              print "[*] No more data. Closing connections..."
              break
  
  def hexdump(src, length=16):
      result = []
      digits = 4 if isinstance(src, unicode) else 2
      for i in xrange(0, len(src), length):
          s = src[i:i+length]
          hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s])
          text = b''.join([x if 0x20 &lt;= ord(x) &lt; 0x7F else b'.' for x in s])
          result.append(b"%04X   %-*s   %s" % (i, length*digits + 1), hexa, text)
      print b'\n'.join(result)
  
  def receive_from(connection):
      buffer = ""
  
      #we set a 2 second timeout; depending on your target, this may need to be adjusted
      connection.settimeout(2)
  
      try:
          #keep reading into the buffer until there's no more data or we time out
          while True:
              data = connection.recv(4096)
              if not data:
                  break
              buffer += data
      except:
          pass
      return buffer
  
  #modify any requests destined for remote host
  def request_handler(buffer):
      #perform packet modifications
      return buffer
  
  #modify any responses destined for the localhost
  def response_handler(buffer):
      #perform packet modification
      return buffer
  
  main()
  </code></pre>
  
  <p>When I run the program, I use: <code>sudo python ./nproxy.py @ @ www.google.com 21 True</code></p>
  
  <p>In order, it calls my program, the first two parameters are shortcuts to automatically connect to the localhost address as well as the port of the host that we're trying to connect to. In this case, it's 21, but I've tried on port 80 as well with the same results. I've also tried about a dozen different websites as well and none seem to be returning my connection requests.</p>
  
  <p>Thank you so much in advance for any advice or help you can give.</p>