I'm having some trouble understanding the security of sockets. I have some code set up in Python, which looks a bit like this:
server.py:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 1234))
s.listen(5)
client.py:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), 1234)
I set myself a project to make a VOIP over LAN, or as close as I can get. I'll be using strictly private IP addresses in this program. I read that opening ports can be dangerous, so I'm a little nervous.
As you can see, I am using the port 1234. Could this introduce a vulnerability from any external threats?
When people say "opening ports can be dangerous" what they mean is that making an application available to connections from an unknown source (such as the Internet) is risky. There may be bugs in the application that allow a remote attacker to execute commands, for example.
As long as you don't accept connections directly from the Internet you're probably fine. If an attacker has access to your LAN, you have more serious things to worry about.
Related
I am trying to create a peer-to-peer python app using the socket library. I am curious to know if there is any way in which I can use the socket library to connect to another computer outside my local network without any manual steps like opening ports on the router for port forwarding. Do I need to use an already open port on the router (given that routers have some ports open on default)? Please guide me. I am new to socket and networking.
My code till now:-
client-1 (sender)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((MYPUBLICIP, 433))
s.send(b"HELLO!")
s.close()
client 2 (receiver)
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((MYPRIVATEIP, 433))
s.listen()
conn, addr = s.accept()
with conn:
print(f"[CONNECTION_ALERT] Received connection request from {addr}.")
while True:
data = conn.recv(1026).decode('utf-8')
if not data:
break
print(data)
The error I am getting:
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
If needed, my python version is 10
Solution to connect two hosts on the same local network
Error message suggest that your firewall probably blocked the network traffic, you can try to disable your firewall and try again, but it is not advisable. If you want to play with network stuff i would suggest you create a local lab that is not connected to internet, like VM's or old laptops/pc.
Solution to connect two hosts NOT on the same local network
If you want to connect two hosts that are not on the same local network then the problem becomes more complicated, and have several possible solutions:
Ask your ISP for public IP (easy but usually comes with extra costs)
Use available software solutions to create private networks over the internet, like hamachi or ngrok (also easy but depending on the usecase cost will vary)
Exploiting naive NAT's by using STUN (hard to implement but satisfying if done right, nice explanation of how it was implemented in OpenTTD multiplayer)
I'm coding a python multiuser chat app. But python doesn't let me connect with computers outside my personal WI-FI zone.
I've tried
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
local_hostname = socket.gethostname()
local_fqdn = socket.getfqdn()
ip_address = socket.gethostbyname(local_hostname)
I've also tried using my ipv4, but it still doesn't work.
In principle, yes.
In practice, most computers are behind a NAT and/or a firewall, either of which will prevent connection.
NAT - This is used to work around limitations in the IPv4 address space size. To avoid it, the destination needs to have a publicly routable address.
Firewall - This is used to filter out attacks. To work with this, the destination firewall needs to be configured to expect your connection.
Is there a way to connect to another computer via their public IP using python sockets, so that you can send data?
In a similar way to which you can connect to a webpage, etc can you do something like this:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, 6000))
I have seen examples of people using this in DOS scripts but can't seem to recreate it. All I get is timeout errors. The only time it worked was when using port 5000 and connecting to my own IP (but all other ports failed), any idea why this happened as well?
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
I'm building an RPC Server in golang that uses msgpack.
The client is built in python using the mprpc library (msgpack over TCP with gevent).
My issue is, being an absolute noob in networking, I discovered that I can't use the same address/port with multiple clients running at once on the same computer (socket already bound i guess, it just stalls and timeouts).
I have looked around quite a bit but I'm not sure what I should be doing to be able to have multiple clients on the same machine talk to a server (msgpack back and forth). Is this a case where I need to use ZeroMQ ? Or requests over HTTP ?
Thanks !
TCP is a connection-oriented protocol. This means that only the server needs to have a fixed, known port. The client can use any port it wants, because nobody is making a connection to the client.
So, how does the server know how to talk to the client? Whenever it accepts a connection, it's told who the connection is from. But usually, you don't even need that, because the socket keeps track of who the connection is from. Just recv and send on that socket, and you're talking to the right client.
You should probably read the Socket Programming HOWTO in the Python docs, or some other tutorial, but briefly…
A server starts like this:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 12345))
sock.listen(5)
while True:
csock, addr = sock.accept()
It binds a port and listens and loops around accepting connections and doing something with them.
A client, on the other hand, just does this:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 12345))
… or, equivalently:
sock = socket.create_connection(('localhost', 12345))
It doesn't call bind, it just creates a connection, letting the sockets library pick an arbitrary port on the appropriate interface for that connection. Unless you've got thousands of sockets already open, it should always be able to find a free port for you.
If you want to have two way connection, then HTTP is not suitable for this. Because HTTP is designed in a way that the server only responds to a request, which prevents server to issue a request itself. There are other solutions that provide two way connection(server to client and client to server in same time).
WebSocket is the first thing that comes to my mind. Of course ZeroMQ also can do this.