This question already has an answer here:
Cannot list FTP directory using ftplib – but FTP client works
(1 answer)
Closed 3 years ago.
I'm connecting to an external FTP/FTPS server using python3 ftplib.FTP_TLS class. When the connection is established in passive mode, the server responds with an internal network IP address like 10.10.XX.XX.
Since I am outside of the network I can't access the server on the provided IP address and ftplib hangs up. Setting the FTPS connection as active doesn't work.
What is the best way to force ftplib to use the original hostname or the external IP address?
The solution I used was from this article. You override the makepasv() method to ignore the returned IP address and use the original host:
class FTP_TLS_IgnoreHost(ftplib.FTP_TLS):
def makepasv(self):
_, port = super().makepasv()
return self.host, port
ftp = FTP_TLS_IgnoreHost('host', 'user', 'password')
There are probably other good solutions, but I thought this was pretty slick.
Related
I'm using PySMB right now:
https://pysmb.readthedocs.io/en/latest/api/smb_SMBConnection.html
and the SMBConnection.connect spec is problematic because it requires knowing the server's IP address.
What about a usage case where I don't know the IP address and looking up the IP address fails? I already went through the steps in https://apple.stackexchange.com/questions/10956/finding-the-remote-ip-address-used-by-a-mounted-smb-share although the server in question isn't a Bonjour service.
I tested using the smb address (that would normally be typed into the Finder's "Connect To Server" option in Mac OS) in the connect function and that didn't work.
Is there an alternative library that takes an SMB address (instead of IP address), or at least a canonical/proper way to translate that into an IP address for this? Either way, please post an example.
I was facing similar kind of issue, did u try making the following changes?
smb = SMBConnection(user_id, password, client, server_name, domain = domain, use_ntlm_v2=True, is_direct_tcp=True)
ip = socket.gethostbyname(server_name)
print(ip)
smb.connect(server_name, 445)
Hy folks,
my problem: I want to start a (tftp) server for an non-existing IP-address.
the server is meant for USB/RNDIS where its IP-address by nature only is existing when there is actual network-traffic going on -- but I want to start the server 'early' (e.g. when Windows starts).
idea was to bind() the socket to 0.0.0.0 - and then to check each request for "valid" addresses.
problem with that approach: recfrom() only returns the source-address (client), but not the destination (server)!
how do I get the IP-address this client has talked to?
(I could of course check for the same subnet at least, but I need the real server-address this client was talking to!)
or, are there by chance any options to let bind() use a non-existing IP-address?
cheers.
p.s.
this is for the Python tftpy server...
-- at the moment I need to ping from client side when starting the server, which is quite meh...
There's no way to get the local address directly but there's a trick that will usually work for you.
Let's say that you just obtained a buffer and client address from recvfrom. Now you create a new auxiliary UDP socket, connect it to the client's address, and then use getsockname to obtain the local address on this new socket. (With UDP, connect doesn't actually send anything to the peer, it just does address resolution.)
So in this way, you can discover the IP address that the server system would use as source were it to send a datagram back to the client system. That's usually the same address that the client used to target the server.
>>> cbytes, caddr = server_sock.recvfrom(2048)
>>> print(caddr) # Client IP and port
('192.168.0.11', 38869)
>>> aux_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> aux_socket.connect((caddr[0], 9999)) # Connect back to client (port doesn't matter)
>>> saddr = aux_socket.getsockname() # Get local IP and port (ignore port here too)
>>> print(saddr)
('192.168.0.12', 39753)
This works on linux. I'm not 100% sure it would work the same way on Windows but it seems reasonable to expect that it would.
I have a client socket behind a NAT and I want to get the local port number used by the process.
To illustrate my question, here's a quick example.
Let's say I create a server using the following code:
welcome_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
welcome_socket.bind(("", 1500))
welcome_socket.listen(5)
I then listen for incoming connections:
(client_socket, address) = self.welcome_socket.accept()
I connect from a client (behind a NAT) using the following code:
sock = socket.create_connection(("server_address", 1500))
Here is where I'm a little confused.
The address I get on the server side has the public address of the WiFi network the client is connected to (which I expect) and some port number, which based on my understanding of NATs, should be different from the actual port number used by the client and is used for address translation.
However, if I used the getsockname() function on the client, I get the same port number as the one given by the server.
Returning to the example in code.
On the server:
client_socket.getpeername()
>>> ('WiFi_address', 4551)
On the client:
sock.getsockname()
>>> ('local_address', 4551)
So, both port numbers are the same, even though the client is behind a NAT. How is this the case? Am I misunderstanding how the NAT works? Or is there another command to get the physical address that the client socket is bound to?
Any insight would be appreciated.
It is likely that the Router is using Port Address Translation (or one-to-many NAT). The wiki link further quotes
PAT attempts to preserve the original source port. If this source port
is already used, PAT assigns the first available port number starting
from the beginning of the appropriate port group 0-511, 512-1023, or
1024-65535. When there are no more ports available and there is more
than one external IP address configured, PAT moves to the next IP
address to try to allocate the original source port again. This
process continues until it runs out of available ports and external IP
addresses.
And that should be the reason why you are seeing port 4551 on the server.
(This link should also help to clarify the difference between NAT and PAT)
I've connected to a database using ftplib as shown below.
import ftplib
sitename = 'ftp.ensembl.org'
connection = ftplib.FTP(sitename)
connection.login()
But because I want to use ssh with an argument of user#host, I believe I need the ip address of the server instead of the url of the ftp site. Is there any code to find and store the ip address of an ftp server within ftplib?
for ssh, you need to use paramiko : http://www.paramiko.org/
here :
http://docs.paramiko.org/en/1.15/api/client.html#paramiko.client.SSHClient.open_sftp
best regard
You can translate a host name to IP address easily in Python using the socket library:
>>> import socket
>>> socket.gethostbyname('www.microsoft.com')
'184.85.88.154'
>>> socket.gethostbyname('ftp.ensembl.org')
'193.62.203.85'
However, I suspect you don't need to do so, as ssh and other utilities will accept hostnames or IP addresses interchangeably. If they require an IP address only, it is usually documented as such.
The hostname ftp.ensembl.org is just a name for the IP address.
In absolute majority on TCP applications/libraries you can use hostname and IP address interchangeably (HTTP/web browser being notable difference).
So with any Python SSH library, you will be able to use the host name too, just as you can use it with ftplib.
That being said, to find an IP address, you can for example use the ping command:
C:\>ping ftp.ensembl.org
Pinging ftp-ensembl-ext.sanger.ac.uk [193.62.203.85] with 32 bytes of data:
Reply from 193.62.203.85: bytes=32 time=51ms TTL=48
Reply from 193.62.203.85: bytes=32 time=51ms TTL=48
So the IP address of your FTP server is 193.62.203.85.
Or google for "DNS lookup".
To address your actual problem: To use the SSH from Python, you do not need an IP address, but rather an SSH library.
Only of the most commonly used SSH libraries for Python is Paramiko.
I would try connect to a counterstrike server hosted on my ip through python socketing ...
import socket
s = socket.socket()
s.connect(("localhost", 27015))
But I would get an error
error: [Errno 10061] No connection could be made because the target machine actively refused it
And I'm sure the server is up, so I'm not sure why it wouldn't connect, I could connect to it in game.
To debug such things you can use Wireshark to observe your Python script while it is trying to connect and compare it to a real client. You may have to listen on the "localhost" interface instead of your physical network interface to see the connection. Your server needs to do the same, so ask your OS to give you a list of bound sockets, including the IPs they are bound to (on Linux netstat -nlp) to check. Maybe the server needs to be configured to allow non-public IPs. Finally, make sure you got the protocol right, TCP (SOCK_STREAM) vs UDP (SOCK_DGRAM).