Reputation: 11
I need to make a request to a specific FTP server and make a LIST/NLST request to get the list of all files (i want to start with at least current dir) without using libraries like ftplib, using only the socket.py. Here's my take on it (the ip, username and password are actually filled, i would prefer not to share them if possible):
port = 21
ip = ""
buff_size = 1024
username = ""
password = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
print(s.recv(buff_size).decode())
s.send("USER {}\r\n".format(username).encode())
print(s.recv(buff_size).decode())
s.send("PASS {}\r\n".format(password).encode())
print(s.recv(buff_size).decode())
s.send("PASV\r\n".encode())
print(s.recv(buff_size).decode())
s.send("LIST\r\n".encode())
print(s.recv(buff_size).decode())
s.send("QUIT\r\n".encode())
print(s.recv(buff_size).decode())
And the response from console is:
220 (vsFTPd 3.0.2)
331 Please specify the password.
230 Login successful.
227 Entering Passive Mode (xx,xxx,xxx,xx,138,136).
425 Failed to establish connection.
221 Goodbye
Before the 227 and 425 codes is a approximately around 1 minute of time until it proceeds to 425. I tried a hell of a lot of different things (i also tried the active instead of the passive mode, but i don't understand how do i get the port, i tried to brute force it and get all the possible combinations of ports from 0 to 255 for both bytes (variables a and b), but to no avail)
s.send("PORT {}\r\n".format("xx,xxx,xxx,xx,"+str(a)+","+str(b)).encode())
but i have zero idea what's might be the cause. I don't know if the reason is network/settings or the code. Ftplibs seem to get the job done right (i first wrote an app using ftplib just to test the given server), so i think it's the code, maybe something about safety (like i'm doing it from console app, and not from browser, and i should send request as one, but i have zero idea how it's done) Just in case i tried switching to a different (mobile) network without router and result is the same (it's not about my ISP or router). Firewall is also turned off for this one. The system is Windows 10, i'm using PyCharm
Upvotes: 0
Views: 657
Reputation: 11
I figured it out, LIST response works. I was sending requests to port 20 and reading responses from 21. I needed to send to 21 and read from 20. Now the code looks as following:
port = 21
ip = ""
buff_size = 1024
username = ""
password = ""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, port))
print(s.recv(buff_size).decode())
s.send("USER {}\r\n".format(username).encode())
print(s.recv(buff_size).decode())
s.send("PASS {}\r\n".format(password).encode())
print(s.recv(buff_size).decode())
s.send("PASV\r\n".encode())
str = s.recv(buff_size).decode()
print(str)
str = str.split(',')
lport = str[-1].replace(').\r\n','')
hport = str[-2]
newport = int(hport)*256+int(lport)
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.connect((ip, newport))
def message_data_send(command):
s1.send(("{}".format(command)+"\r\n").encode())
print(s.recv(buff_size).decode())
def message_command_send(command):
s.send(("{}".format(command)+"\r\n").encode())
print(s.recv(buff_size).decode())
if command=='NLST':
print(s.recv(buff_size).decode())
print(s1.recv(buff_size).decode())
if command=='LIST':
s.recv(buff_size).decode()
print(s1.recv(buff_size).decode())
message_command_send('LIST')
Upvotes: 1