I want to start a project to learn python, and I chose to write a simple web proxy.
In some case, some thread seems get a null request, and python rasie exception:
first_line: GET http://racket-lang.org/ HTTP/1.1
Connect to: racket-lang.org 80
first_line:
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 551, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 504, in run
self.__target(*self.__args, **self.__kwargs)
File "fakespider.py", line 37, in proxy
url = first_line.split(' ')[1]
IndexError: list index out of range
first_line: first_line: GET http://racket-lang.org/plt.css HTTP/1.1GET http://racket-lang.org/more.css HTTP/1.1
Connect to:Connect to: racket-lang.orgracket-lang.org 8080
My code was simple.
I don't know what's going on, any help would be appreciated:)
from threading import Thread
from time import time, sleep
import socket
import sys
RECV_BUFFER = 8192
DEBUG = True
def recv_timeout(socks, timeout = 2):
socks.setblocking(0);
total_data = []
data = ''
begin = time()
while True:
if total_data and time() - begin > timeout:
break
elif time() - begin > timeout * 2:
break
try:
data = socks.recv(RECV_BUFFER)
if data:
total_data.append(data)
begin = time()
else:
sleep(0.1)
except:
pass
return ''.join(total_data)
def proxy(conn, client_addr):
request = recv_timeout(conn)
first_line = request.split('\r\n')[0]
if (DEBUG):
print "first_line: ", first_line
url = first_line.split(' ')[1]
http_pos = url.find("://")
if (http_pos == -1):
temp = url
else:
temp = url[(http_pos + 3):]
port_pos = temp.find(":")
host_pos = temp.find("/")
if host_pos == -1:
host_pos = len(temp)
host = ""
if (port_pos == -1 or host_pos < port_pos):
port = 80
host = temp[:host_pos]
else:
port = int((temp[(port_pos + 1):])[:host_pos - port_pos - 1])
host = temp[:port_pos]
print "Connect to:", host, port
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send(request)
data = recv_timeout(s)
if len(data) > 0:
conn.send(data)
s.close()
conn.close()
except socket.error, (value, message):
if s:
s.close()
if conn:
conn.close()
print "Runtime error:", message
sys.exit(1)
def main():
if len(sys.argv) < 2:
print "Usage: python fakespider.py <port>"
return sys.stdout
host = "" #blank for localhost
port = int(sys.argv[1])
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(50)
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket:", message
sys.exit(1)
while 1:
conn, client_addr = s.accept()
t = Thread(target=proxy, args=(conn, client_addr))
t.start()
s.close()
if __name__ == "__main__":
main()
The stack trace you see says everything:
url = first_line.split(' ')[1]
IndexError: list index out of range
Apparently the result of splitting variable first_line is not a list having more than one element, as you assumed. So it contains something different than you expected. To see what it actually contains just print it out:
print first_line
or use a debugger.
Related
i have an university project with python which i have to write a proxy server that waits for a request from a client and then connects the client to the server. i searched the net and found an already-written code from this site:
https://www.geeksforgeeks.org/creating-a-proxy-webserver-in-python-set-1/
so i used it and made some changes in the code and add the public server and port to it
but when i run it i get this error:
line 33, in main
request = conn.recv(4096)
NameError: name 'conn' is not defined
so i'm not very familiar with sockets and python so if there are obvious mistakes in the code i would be happy if u guys could explain them in a very basic way so my amateur butt would understand it lol
this is the code:
import signal
import socket
import threading
class Proxy:
def __init__(self):
# creating a tcp socket
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# reuse the socket
self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.ip = 'localhost'
self.port = 8080
self.serverSocket.bind((self.ip, self.port))
self.serverSocket.listen(10)
self.__clients = {}
def shutdown(self):
# shutdown on cntrl c
signal.signal(signal.SIGINT, self.shutdown)
def multirequest (self):
while True:
# establish the connection
(clientSocket, client_address) = self.serverSocket.accept()
d = threading.Thread(name=self._getclientname(client_address),
target=self.proxy_thread,
args=(clientSocket, client_address))
d.setDaemon(True)
d.start()
def main(self, conn):
# get the request from browser
request = conn.recv(4096)
# parse the first line
first_line = request.split('\n')[0]
# get url
url = first_line.split(' ')[1]
http_pos = url.find("://")
if http_pos == -1:
temp = url
else:
temp = url[(http_pos + 3):]
webserver = ""
port = -1
port_pos = temp.find(":")
# find end of web server
webserver_pos = temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
if port_pos == -1 or webserver_pos < port_pos:
# default port
port = 80
webserver = temp[:webserver_pos]
else: # specific port
port = int((temp[(port_pos + 1):])[:webserver_pos - port_pos - 1])
webserver = temp[:port_pos]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.connect((webserver, port))
s.sendall(request)
while 1:
# receive data from web server
data = s.recv(4096)
if len(data) > 0:
conn.send(data) # send to browser/client
else:
break
p = Proxy()
p.main()
In python, the common pattern for executables is like this:
def main(): # Or whatever name you want to use
"""Your code here"""
# If you are importing the code, the condition will evaluate to false.
if __name__ == "__main__":
main()
Have in mind that you can use whatever function name you want.
You need to put your code inside of a class like this. Any variables you plan to use through your code, define inside of the __init__ method, this could be for example your self.serverSocket, ip, port number, etc.
The init method is deigned to run once, once you create an instance of the class, it usually stores variables. The main method or any other methods you define, would be where you put the rest of your code.
import signal
import socket
import threading
class proxy():
def __init__(self):
# creating a tcp socket
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# reuse the socket
self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.your_ip = "127.0.0.1" # loop back address
self.your_port = 80 # use a port thats open like port 80
def shutdown(self):
# add your signal shutdown code here
pass
def main(self):
# shutdown on cntrl c
signal.signal(signal.SIGINT, self.shutdown)
self.serverSocket.bind((self.your_ip, self.your_port))
self.serverSocket.listen(10)
self.__clients = {}
while True:
# establish the connection
(clientSocket, client_address) = self.serverSocket.accept()
d = threading.Thread(name=self._getClientName(client_address),
target=self.proxy_thread,
args=(clientSocket, client_address))
d.setDaemon(True)
d.start()
# get the request from browser
request = conn.recv(4096)
# parse the first line
first_line = request.split('\n')[0]
# get url
url = first_line.split(' ')[1]
http_pos = url.find("://")
if http_pos == -1:
temp = url
else:
temp = url[(http_pos + 3):]
port_pos = temp.find(":")
# find end of web server
webserver_pos = temp.find("/")
if webserver_pos == -1:
webserver_pos = len(temp)
webserver = ""
port = -1
if port_pos == -1 or webserver_pos < port_pos:
# default port
port = 80
webserver = temp[:webserver_pos]
else: # specific port
port = int((temp[(port_pos + 1):])[:webserver_pos - port_pos - 1])
webserver = temp[:port_pos]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
s.connect((webserver, port))
s.sendall(request)
while 1:
# receive data from web server
data = s.recv(4096)
if len(data) > 0:
conn.send(data) # send to browser/client
else:
break
p = proxy()
p.main()
I successful make a local python proxy via socket module: https://github.com/wayne931121/Python_Proxy_Server/blob/main/Proxy.py
It can run http and https request.
Code:
#!/usr/bin/env python
# coding: utf-8
# In[ ]:
# 參考資料
# https://docs.python.org/3/library/socket.html
# https://stackoverflow.com/questions/24218058/python-https-proxy-tunnelling
# https://stackoverflow.com/questions/68008233/proxy-server-with-python/73851150#73851150
import sys
#import ssl
import time
import signal
import socket
#import certifi
import threading
with open("log.txt", "w") as f:
f.write("")
def signal_handler(sig, frame):
print('Proxy is Stopped.')
sys.exit(0)
def write(*content, prt=False):
if prt :
if len(content[0])<100:
print(*content)
else:
print("This message is too long not print in cmd but will store at log.txt.")
if type(content[0])==bytes:
content = b" ".join(content)
else:
content = bytes(" ".join(content), encoding="utf-8")
with open("log.txt", "ab") as f:
f.write(content+b"\n")
class Proxy:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # creating a tcp socket
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # reuse the socket
self.ip = "127.0.0.1"
self.port = 8080
# self.host = socket.gethostbyname(socket.gethostname())+":%s"%self.port
self.sock.bind((self.ip, self.port))
self.sock.listen(10)
print("Proxy Server Is Start, See log.txt get log.")
print("Press Ctrl+C to Stop.")
start_multirequest = threading.Thread(target=self.multirequest)
start_multirequest.setDaemon(True)
start_multirequest.start()
while 1:
time.sleep(0.01)
signal.signal(signal.SIGINT, signal_handler)
def multirequest(self):
while True:
(clientSocket, client_address) = self.sock.accept() # establish the connection
client_process = threading.Thread(target=self.main, args=(clientSocket, client_address))
client_process.setDaemon(True)
client_process.start()
def main(self, client_conn, client_addr): # client_conn is the connection by proxy client like browser.
origin_request = client_conn.recv(4096)
request = origin_request.decode(encoding="utf-8") # get the request from browser
first_line = request.split("\r\n")[0] # parse the first line
url = first_line.split(" ")[1] # get url
http_pos = url.find("://")
if http_pos == -1:
temp = url
else:
temp = url[(http_pos + 3):]
webserver = ""
port = -1
port_pos = temp.find(":")
webserver_pos = temp.find("/") # find end of web server
if webserver_pos == -1:
webserver_pos = len(temp)
if port_pos == -1 or webserver_pos < port_pos: # default port
port = 80
webserver = temp[:webserver_pos]
else: # specific port
port = int(temp[(port_pos + 1):])
webserver = temp[:port_pos]
write("Connected by", str(client_addr))
write("ClientSocket", str(client_conn))
write("Browser Request:")
write(request)
server_conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_conn.settimeout(1000)
try:
server_conn.connect((webserver, port)) # "server_conn" connect to public web server, like www.google.com:443.
except: # socket.gaierror: [Errno 11001] getaddrinfo failed
client_conn.close()
server_conn.close()
return
if port==443:
client_conn.send(b"HTTP/1.1 200 Connection established\r\n\r\n")
client_conn.setblocking(0)
server_conn.setblocking(0)
write("Connection established")
# now = time.time()
client_browser_message = b""
website_server_message = b""
error = ""
while 1:
# if time.time()-now>1: # SET TIMEOUT
# server_conn.close()
# client_conn.close()
# break
try:
reply = client_conn.recv(1024)
if not reply: break
server_conn.send(reply)
client_browser_message += reply
except Exception as e:
pass
# error += str(e)
try:
reply = server_conn.recv(1024)
if not reply: break
client_conn.send(reply)
website_server_message += reply
except Exception as e:
pass
# error += str(e)
write("Client Browser Message:")
write(client_browser_message+b"\n")
write("Website Server Message:")
write(website_server_message+b"\n")
# write("Error:")
# write(error+"\n")
server_conn.shutdown(socket.SHUT_RDWR)
server_conn.close()
client_conn.close()
return
server_conn.sendall(origin_request)
write("Website Host Result:")
while 1:
# receive data from web server
data = server_conn.recv(4096)
try:
write(data.decode(encoding="utf-8"))
except:
write(data)
if len(data) > 0:
client_conn.send(data) # send to browser/client
else:
break
server_conn.shutdown(socket.SHUT_RDWR)
server_conn.close()
client_conn.close()
Proxy()
I'm trying to send a large file (.avi) over socket by sending the content of the file in chunks (a little bit like torrents). The problem is that the script doesn't send the file. I'm out of ideas here.
Any help or twerking of the script would be very appreciated.
Server:
import socket
HOST = ""
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
conn, addr = sock.accept()
print("Connected by ", str(addr))
while 1:
data = conn.recv(1024)
if data.decode("utf-8") == 'GET':
with open(downFile,'rb') as output:
l = output.read(1024)
while (l):
conn.send(l)
l = output.read(1024)
output.close()
conn.close()
Client:
import socket
HOST = "localhost"
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST,PORT))
while 1:
message = input()
sock.send(bytes(message,'UTF-8'))
conn.send(str.encode('GET'))
with open(downFile, 'wb+') as output:
while True:
rec = str(sock.recv(1024), "utf-8")
if not rec:
break
output.write(rec)
output.close()
print('Success!')
sock.close()
Here are a working client and server that should demonstrate transferring a file over a socket. I made some assumptions about what your code was supposed to do, for example, I assumed that the initial message the client sent to the server was supposed to be the name of the file to download.
The code also includes some additional functionality for the server to return an error message to the client. Before running the code, make sure the directory specified by DOWNLOAD_DIR exists.
Client:
import socket
import sys
import os
HOST = "localhost"
PORT = 8050
BUF_SIZE = 4096
DOWNLOAD_DIR = "downloads"
def download_file(s, down_file):
s.send(str.encode("GET\n" + down_file))
rec = s.recv(BUF_SIZE)
if not rec:
return "server closed connection"
if rec[:2].decode("utf-8") != 'OK':
return "server error: " + rec.decode("utf-8")
rec = rec[:2]
if DOWNLOAD_DIR:
down_file = os.path.join(DOWNLOAD_DIR, down_file)
with open(down_file, 'wb') as output:
if rec:
output.write(rec)
while True:
rec = s.recv(BUF_SIZE)
if not rec:
break
output.write(rec)
print('Success!')
return None
if DOWNLOAD_DIR and not os.path.isdir(DOWNLOAD_DIR):
print('no such directory "%s"' % (DOWNLOAD_DIR,), file=sys.stderr)
sys.exit(1)
while 1:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except Exception as e:
print("cannot connect to server:", e, file=sys.stderr)
break
file_name = input("\nFile to get: ")
if not file_name:
sock.close()
break
err = download_file(sock, file_name)
if err:
print(err, file=sys.stderr)
sock.close()
Server:
import socket
import sys
import os
HOST = ""
PORT = 8050
BUF_SIZE = 4096
def recv_dl_file(conn):
data = conn.recv(1024)
if not data:
print("Client finished")
return None, None
# Get command and filename
try:
cmd, down_file = data.decode("utf-8").split("\n")
except:
return None, "cannot parse client request"
if cmd != 'GET':
return None, "unknown command: " + cmd
print(cmd, down_file)
if not os.path.isfile(down_file):
return None, 'no such file "%s"'%(down_file,)
return down_file, None
def send_file(conn):
down_file, err = recv_dl_file(conn)
if err:
print(err, file=sys.stderr)
conn.send(bytes(err, 'utf-8'))
return True
if not down_file:
return False # client all done
# Tell client it is OK to receive file
sent = conn.send(bytes('OK', 'utf-8'))
total_sent = 0
with open(down_file,'rb') as output:
while True:
data = output.read(BUF_SIZE)
if not data:
break
conn.sendall(data)
total_sent += len(data)
print("finished sending", total_sent, "bytes")
return True
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
keep_going = 1
while keep_going:
conn, addr = sock.accept()
print("Connected by", str(addr))
keep_going = send_file(conn)
conn.close() # close clien connection
print()
sock.close() # close listener
i am trying to create a proxy server script with python when i run it i have this arror messages please can i know what are the mistakes i've done and how to avoid them (i sow the script on a site)
how the script looks like !
import socket
from thread import *
import sys
host = ""
port = 91
def start():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(5)
print "[+] listening ..."
while True:
try:
connection, address = s.accept()
data = connection.recv(1024)
start_new_thread(conn_string, (data, connection))
except KeyboardInterrupt:
print "\n\nclosing !"
def conn_string(data, con):
webserver = ""
portserver = 0
f_li = data.split('\n')[0]
lien = f_li.split(' ')[1]
http_pos = lien.find("://")
if http_pos == -1:
url = lien
else:
url = lien[(http_pos+3):]
port_pos = url.find(':')
if port_pos == -1:
portserver = 80
else:
portserver = url[(port_pos+1):]
s_pos = url.find('/')
if s_pos == -1:
webserver = url
else:
webserver = url[:(s_pos)]
proxy_server(webserver, portserver, data, con)
def proxy_server(webserver, portserver, data, con):
print webserver
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((webserver, int(portserver)))
s.send(data)
while True:
red = s.recv(8192)
if len(red) > 0:
con.send(red)
start()
this is one of the error messages that i have !
Unhandled exception in thread started by <function conn_string at 0x0248CEF0>
Traceback (most recent call last):
File "C:\Users\none2\Desktop\Nouveau dossier\Target.py", line 52, in conn_stri
ng
proxy_server(webserver, portserver, data, con)
File "C:\Users\none2\Desktop\Nouveau dossier\Target.py", line 57, in proxy_ser
ver
s.connect((webserver, int(portserver)))
File "C:\Python27\lib\socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.gaierror: [Errno 11004] getaddrinfo failed
can you replace
start_new_thread(conn_string, (data, connection))
line with
start_new_thread(conn_string(data, connection))
tried running the same file, it seems above one is the only error
I try to make a chat on Python3. Here is my code:
import socket
import threading
print("Server starts working")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 57054))
sock.listen(2)
conn, addr = sock.accept()
def get_message():
while True:
data = sock.recv(1024).decode()
if len(data) != 0:
print("Some guy: ", data)
def send_message():
while True:
message = input()
if len(message) != 0:
message = str.encode(message)
sock.send(message)
print("You: ", message)
def run():
get_message_thread = threading.Thread(target=get_message())
send_message_thread = threading.Thread(target=send_message())
get_message_thread.daemon = True
send_message_thread.daemon = True
get_message_thread.start()
send_message_thread.start()
run()
sock.close()
But after the execution and sending a message from other client I get an error message:
Server starts working
Traceback (most recent call last):
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 40, in <module>
run()
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 30, in run
get_message_thread = threading.Thread(target=get_message())
File "/home/ptrknvk/Documents/Study/Python/chat/chat.py", line 15, in get_message
data = sock.recv(1024).decode()
OSError: [Errno 107] Transport endpoint is not connected
Process finished with exit code 1
I've read, that there are some troubles with sock.accept(), but everything's alright here, as I think.
Your program has many flaws. As zondo mentioned, you are incorrectly passing the target. They should be like threading.Thread(target=get_message). Second problem is, you should use conn (and not sock) for sending and receiving data. Third problem is, main thread was blocking at accept call and will wait for the connection. But soon as it accepts a connection, it will exit. From the main thread, you should wait for get_message_thread and send_message_thread. Try the modified code:
import socket
import threading
print("Server starts working")
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 57054))
sock.listen(2)
conn, addr = sock.accept()
def get_message():
while True:
data = conn.recv(1024).decode()
if len(data) != 0:
print("Some guy: ", data)
def send_message():
while True:
message = input()
if len(message) != 0:
message = str.encode(message)
conn.send(message)
print("You: ", message)
def run():
get_message_thread = threading.Thread(target=get_message)
send_message_thread = threading.Thread(target=send_message)
get_message_thread.daemon = True
send_message_thread.daemon = True
get_message_thread.start()
send_message_thread.start()
get_message_thread.join()
send_message_thread.join()
run()
sock.close()
Here is the serve code:
from socket import *
from time import ctime
HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
try:
while True:
print 'Wait for connection...'
tcpCliSock, addr = tcpSerSock.accept()
print '...connnet from:', addr
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('[%s] %s' % (ctime(), data))
tcpCliSock.close()
except (EOFError, KeyboardInterrupt):
tcpSerSock.close()
Here is the client code:
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = raw_input(">")
if not data:
break
tcpCliSock.send(data)
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
print data
break
tcpCliSock.close()
When I run serve code, it shows:
Traceback (most recent call last):
File "G:/python/tcpServ&tcpClnt/tsTserv.py", line 22, in <module>
data = tcpCliSock.recv(BUFSIZ)
File "C:\Python27\lib\socket.py", line 170, in _dummy
raise error(EBADF, 'Bad file descriptor')
socket.error: [Errno 9] Bad file descriptor
But client could still get the information. Then I changed the code in socket.py, it worked! But I don't know why.
PS. I changed:
class _closedsocket(object):
__slots__ = []
def _dummy(*args):
raise error(EBADF, 'Bad file descriptor')
to this:
class _closedsocket(object):
__slots__ = []
def _dummy(*args):
pass
The error occurs because you call recv() of the afore closed socket. Sequence of execution:
…
data = tcpCliSock.recv(BUFSIZ) # data from tcpCliSock.send(data) is received
# not true: if not data:
# skipped: break
tcpCliSock.send('[%s] %s' % (ctime(), data)) # reply data is sent to client
tcpCliSock.close() # the socket is closed!
while True: # the loop is reiterated
data = tcpCliSock.recv(BUFSIZ) # the closed socket is used!
Perhaps you just by mistake indented the tcpCliSock.close() wrongly. If you outdent it, all works:
while True:
data = tcpCliSock.recv(BUFSIZ)
if not data:
break
tcpCliSock.send('[%s] %s' % (ctime(), data))
tcpCliSock.close()
Then I changed the code in socket.py, it worked! But I don't know why.
By changing raise … to pass, you just swept the error under the carpet.