Python socket not accepting external connections - python

I have a python socket that is supposed to be listening to all incoming sockets on port 2022 and I have port forwarding enabled as well as a dynamic DNS service. When I am connected to the same network and I try to connect to my pc using the pc's IP address it works like a charm but when I try to use the public IP of my network it won't work although I have done proper port forwarding. Here is my code, it stucks on the last line and doesn't accept any connections outside the network:
IPC= '0.0.0.0'
PORTC =2022
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.bind((IPC,PORTC))
client_socket.listen(5)
connection =client_socket.accept()[0].makefile('wb')

If you can connect from a different PC inside your private network, then there's nothing wrong with your Python code. It's almost certain that there's something wrong with your router or the port forwarding config.
Make sure that you've re-reviewed your port forwarding settings and perhaps try restarting the router (be careful to verify your internally assigned IP addresses haven't changed if you go this route).

Related

Why "[Errno 61] Connection refused" when program is listening on correct port, socket is bound to all interfaces?

I'll try be concise, but please let me know if I can provide any more helpful pieces of information.
I have client and server Python programs, and they work fine when ran on the same machine, and when the client connects to my machine's local IP (not 127.0.0.1, but the IP assigned to my machine). I have not been able to get this to work with my public IP.
I get a [Errno 61] Connection refused error when I try to get the client to connect to my router's public IP address. My server binds to all interfaces using bind(("0.0.0.0", 50000)), and I already set up port forwarding for my router. I verified that the program is listening on that port by running netstat -an | grep LISTEN and finding the following line:
tcp4 0 0 *.50000 *.* LISTEN
I can also seemingly reach the port through an online port checking tool, which shows that the port is open when I am running my program, and closed when I close that program. My program also registers the connection from this tool.
The fact that my program accepts the connection from the port checking tool gives me the impression that my client code is missing something, but I can't find any answers. It might be worth noting that I am still running my server and client code on the same machine, but I'm not sure why that would derail things. Here's the code I use to connect on the client side:
tcp_client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
tcp_client.connect(('my_public_ip', 50000))
Are there any diagnostic steps that I can follow to narrow down my issue?
Before you spend any more time on this, try connecting to your public ip from a computer outside your home network. Spend a couple of dollars on an AWS instance for an hour if you have to, or try connecting from a friend's machine, whatever. It will probably work just fine.
I suspect the problem is simply that you cannot, from inside your home network, connect to your router's public ip address. I tried the same thing with my local network and ran into the same behavior.
If you really need to your public ip during development, you can just assign that as an alias to one of your local interfaces (ip addr add 1.2.3.4/32 dev eth0)...but it's probably easier just to use your an address on your local network, or just arrange for regular access to a remote system for testing.

Socket Programming over WLAN

I am trying to create an android app which connects to a socket created on the desktop. I did a lot of testing and figured out that my routing was giving me a hard time.
When I tried to connect over a mobile hotspot, it was working perfectly fine. But when I connected over the router, my connection was getting rejected or something. I tried connecting both ways, one with my android as serversocket and one with my desktop as server socket.
I think the issue is because of port forwarding or something, but since I'm new to networking, I don't know how to configure it.
I looked up online and tried some stuff myself, however nothing worked.
This is how my D-Link router port forwarding setup is.
D-Link router
I have a socket running at port 8080 hosted by my android device with ip 192.168.0.122 and my laptop is at ip 192.168.0.123
This is client code which i have on my laptop(client.py)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = input("IP: ")
port = int(input("Port: "))
s.connect((ip,port))
print(s)
s.send(bytes(str("Hello!"), "utf-8"))
I am using python(spyder) to connect as client by enterring the socket ip address and the port number.
The main problem I am facing is the weird behaviour of it working sometimes and then after like a few hours, it just stops working without doing anything. Then I try the same method I did last time to make it work, but it still doesn't work. I feel like my router is moody and only works when it wants to, and that is the weird behaviour.

How send data between two devices using sockets in Python?

I'm using this code for the client:
import socket
HOST = "Server IP"
PORT = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
s.close()
And this code for the server:
import socket
HOST = "Client IP"
PORT = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
s.close()
and what I'd like to do is simply send some data from a device to another. The problem is that I could make it work just by sending data on devices on the same network (that is, send data from a CMD window to another, or send data from the PC to the phone, where I have Termux with Python installed, if the PC and the phone are connected to the same network).
However, how do I send data between two different networks? I suppose that in the HOST variable on the client side I should put the public IP address of the server and in the HOST variable on server side I should put the public IP address of the client right?
But then suppose that in the client network there are many devices connected, where do I specify the private IP address of the client to send the data to a specific device?
The short answer is that you can't -- most routers connected to the Internet these days include a firewall and/or NAT, both of which are explicitly designed to prevent Internet packets from the outside world from getting to devices on the local LAN, for security reasons. In particular, the private addresses assigned to devices on the LAN (192.168.1.5, 10.0.0.10, and so on) are non-routable, so they are not meaningful outside the context of the local network and cannot be used to route traffic across the Internet.
Obviously that's not the full answer, though, since various peer-to-peer programs in use today (e.g. Skype) do manage to communicate in the way you want to do; however, they all have to work around the above problem one way or another. Some ways they do it include:
Have the user of the LAN that is to receive the incoming TCP connection configure port forwarding on his router. This tells the router that any TCP connections received on a particular port should be automatically forwarded to the specified private IP address on the LAN. Downsides of this approach are that it opens a hole in the user's firewall that might be later exploited by bad actors, and that many users aren't willing (or even able) to reconfigure their routers in this way.
Run a server with an Internet-facing IP address, and have your program always connect to it. This server can then work as a proxy, forwarding TCP data from one connection to the other as necessary. This avoids the problem, at the cost of having to maintain your own 24/7 public-facing server and route all your traffic through it.
Use TCP hole punching to convince the router(s) to allow your incoming TCP connections by exploiting the rules/logic they (sometimes) use to decide when to allow incoming traffic. This gets you the direct connections you want, but it's fairly complicated to set up, doesn't work on all routers, and generally requires the implementation of step (2) (above) as a prerequisite, since the connection-bootstrapping process itself requires some communication that must be facilitated by a third-party.
to work, change s.listen() to s.listen(5)
I was able to connect from my network 192.168.1.x to other 192.168.2.x
Now, depending of your requirements you will need some configuration to work in the Internet.
the clients should have the IP depending the localization of your server, if server application is:
Connected direct to the Internet, client should have gateway IP address
Connected to a router, you can configure a DMZ (not recommended, not secure, just for tests) or configure ports (secure and recommended), the clients should have the gateway IP address of the router

Ports with python sockets, are they random?

I am trying to learn python sockets, but am becoming very confused by the results of the example code from the website (found here).
The only modification I have made is replacing socket.gethostname() in the server with the local IP of my server, to allow me to run this on two computers.
When I connect, attempting to connect on port 12345 as in the example, I get this output:
Got connection from ('10.0.1.10', 37492)
This leads me to believe that it is connecting on port 37492. I would like it to connect on the port I tell it to, so I can port forward. Am I misunderstanding, or is there an extra command to specify it.
Edit: I am uploading my code:
Client.py
#!/usr/bin/python # This is client.py file
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.connect(("10.0.1.42", port))
print s.recv(1024)
s.close # Close the socket when done
Server.py
import socket
s = socket.socket() # Create a socket object
host = "10.0.1.42" # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close() # Close the connection
You have reached that point in your networking life where you need to understand protocol multiplexing. Good for you.
Think of the TCP/IP stack. An application communicates with a remote application by passing application-layer data to the transport (end-to-end) layer, which passes it to the network layer (internetwork layer) which tries, without guarantees, to have packets reach the IP destination host over a sequence of hops determined by cooperating routers that dynamically update their routing tables by talking to connected routers. Each router conversation goes over a physical transport of some kind (ISDN, Ethernet, PPP - in TCP/IP the task of creating packets and transmitting the appropriate bit stream is regarded as a single "subnetwork" layer, but this is ultimately split into two when differentiation is required between the OSI physical layer (Layer 1) and the data link layer (layer 2) for protocols like DHCP.
When TCP and UDP were designed, the designers imagined that each server would listen on a specific port. This typically has the inherent limitation that the port can only handle one version of your service protocol (though protocols like HTTP take care to be backwards-compatible so that old servers/clients can generally interoperate with newer ones). There is often a service called portmapper running on port 111 that allows servers to register the port number they are running on, and clients to query the registered servers by service (program) number and protocol version. This is a part of the Sun-designed RPC protocols, intended to expand the range of listening ports beyond just those that were pre-allocated by standards. Since the preallocated ports were numbered from 1 to 1023, and since those ports typically (on a sensible operating system) require a high level of privilege, RPC also enabled non-privileged server processes as well as allowing a server to be responsive to multiple versions of network application protocols such as NFS.
However the server side works, the fact remains that there has to be some way for the network layer to decide which TCP connection (or UDP listener) to deliver a specific packet to. Similarly for the transport layer (I'll just consider TCP here since it's connection-oriented - UDP is similar, but doesn't mind losing packets). Suppose I'm a server and I get two connections from two different client processes on the same machine. The destination (IP address, port number) will be the same if the clients are using the same version of the same protocol, or if the service only listens on a single port.
The server's network layer looks at the incoming IP datagram and sees that it's addressed to a specific server port. So it hands it off to that port in the transport layer (the layer above the network layer). The server, being a popular destination, may have several connections from different different client processes on the same machine. This is where the magic of ephemeral ports appears.
When the client requests a port to use to connect to a service, the TCP layer guarantees that no other process on that machine (technically, that interface, since different interfaces have unique IP addresses, but that's a detail) will be allocated the same port number while the client process continues to use it.
So protocol multiplexing and demultiplexing relies on five pieces of information:
(sender IP, sender port, protocol, receiver IP, receiver port)
The protocol is a field in the IP header as are the source and destination IP addresses. The sending and receiving port numbers are in the transport layer segment header.
When an incoming packet arrives, the guaranteed uniqueness of different ephemeral ports from the same client (endpoint) allows the transport layer to differentiate between different connections to the same server IP address from the same client IP address and port (the worst case for demultiplexing) by their source IP address and port. The (transport) protocol is included to ensure that TCP and UDP traffic don't get mixed up. The TCP/UDP constraints on uniqueness of ephemeral ports guarantee that any server can only receive one connection from a specific combination of (IP address, port number) and it's that that allows connections from the same machine to be demultiplexed into separate streams corresponding to the different origins.
In Python when you connect a socket to a remote endpoint the socket.accept() call returns the (IP address, port number) pair for the remote endpoint. You can use that to discover who is communicating with you, but if you just want to talk back you can simply write() the socket.
The key word is "from." That's the port that the client is connecting from, 12345 is the one your server is listening on and the client is connecting to.
The message that appears comes from the server. It just gives you information that connection was established from the client's port 37492.
This is what happens:
Your server (server.py) is listening on port 12345. Your client (client.py) connects to the port 12345 of the server. The TCP connection is always established between two ports - source and destination.
So, looking from your client app perspective 12345 is the destination port and 37492 is the source port. In other words client establishes a connection from its local port 37492 to the remote servers port 12345.
If you want to set up port forwarding you may still do it as the port on which server listens is well known (12345) and the source port of the client doesn't really matter in this situation.
The port that you get in your output is the source port. Your client program sends to the server on the port you choose (in this case, 12345), but it also needs a port to receive data sent by the server, so it randomly chooses a source port and tells it to the server.
I suggest you read some more about TCP and ports in general.

Capture destination IP in TCP Python SocketServer

I have a Python script that is running on a Linux server that has a dozen IP addresses associated with it. I implemented a TCPSServer from Python's socketserver library and had it listen on all network interfaces.
Several devices will be connecting to this server, and we need to be able to somehow capture the ip address of the destination (not the IP address of the client, but the IP address of the server that the client thinks it is connecting to). Right now, I can receive client connections, I can see the client IP, but I cannot figure out a method for obtaining the destination IP.
Does anyone know a method for capturing the destination IP on the socketserver class? It would seem if I can listen to multiple interfaces, there would be a way to tell which interface was hit.
This will be installed on several servers eventually, each with an unknown number of network interfaces. However, we do know that this will only exist on Linux bases systems. So if there was an OS specific way to do this, I would be fine with that as well.
If you have a socket object, you can use socket.getsockname() to obtain the IP address it's bound to. So something along the lines of:
# IPv4
client = listening_socket.accept()
(ipv4,port) = client.getsockname()
# IPv6
client = listening_socket.accept()
(address, port, flow_info, scope_id) = client.getsockname()
Never tested it on a multihomed server with a socket bound to all interfaces though - might return IPv4 0.0.0.0 or the IPv6 equivalent, for all I know, which wouldn't be all that useful.

Categories