First computer doesn't receive UDP packet sent from Second computer - python

Today i was trying Python's socket module, but i failed to send/recieve from one PC to another.
At first i tried doing everything on single PC:
Receiver:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip = socket.gethostbyname(socket.gethostname())
port = 5003
s.bind((ip, port))
while True:
data, addr = s.recvfrom(1024)
print(data, addr)
Sender:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip = # I wrote ip manually from socket.gethostbyname(socket.gethostname())
port = 5003
s.sendto("Hello!", (ip, port))
Doing first script on first command line and other on second, on single PC, would work fine. But doing from one PC to another would not.
Whenever i executed Receiver script on first PC, and Sender script on second PC, there were no updates, First PC couldn't receive packet.
Also sending packet from PC2 to PC1 works, but vice versa doesn't.
Operating systems:
PC2 = Windows 8.1 64 bit;
PC1 = Mac OS X El Capitan 10.11.1 64 bit;
I have also tried adding outbound rule in Windows firewall, allowing all connections for specific port.
What could the problem be? Is it because of firewall? If not then am i doing this incorrectly?

Found the problem:
Short:
socket.gethostbyname(socket.gethostname()) contained IPv4 address of VirtualBox. Wireless LAN adapter IPv4 was different, and would receive UDP packet.
Long:
I was looking for Wireless Lan Adapter IPv4 address in ipconfig would be same in socket.gethostbyname(socket.gethostname()), but turns out
socket.gethostbyname(socket.gethostname()) would give the address of VirtualBox Host-Only Network.
When i pinged the VM IPv4 it would give timeout request, but after pinging real local IPv4 it did work.
Fix:
When oracle virtualbox are set, How to get local ip address in python

Related

How is the IP address returned by python socket.gethostbyname(socket.gethostname()) determined when I'm connected to multiple networks

I'm just getting started with Python socket module. I have this server code that creates a socket and listen for connection from a client script...
server.py
import socket
hostname = socket.gethostbyname(socket.gethostname())
port = 5555
connection = socket.socket()
connection.bind((hostname, port))
connection.listen(5)
client, addr = connection.accept()
# do something with client...
I'm curious to know how the hostname is determine or which hostname (ip address) is used when the PC running the script is connected on multiple networks
for example, I use netsh wlan start hostednetwork on windows command prompt for an hosted network (to which the other device running the client script is connected on) and the PC is also connected to a router and lastly to Ethernet via USB tethering to an Android phone, making a total of three networks the PC is connected to, and when I run ipconfig on the command prompt, three different IPv4 addresses are listed, which of these three will be returned by gethostbyname(gethostname())? And how is it determined.
Thank you in advance.

Socket module (python) works but doesn't use specified port number?

I'm using the socket module from Python 3.7 (shouldn't matter, as I tried activating a different Python version from different venv's).
The problem is that I've created a TCP connection listening at port 65432, an arbitrary number that I selected for this simple demo.
server.py looks like the following:
import socket
HOST = '127.0.0.1' # Standard loopback interface address (localhost)
PORT = 65432 # Non-privileged ports are > 1024
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data:
break
conn.sendall(data)
client.py is relatively straightforward as it makes a connection with 127.0.0.1:65432.
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # Port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
# Send its message and then read the server's reply and prints it
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
Executing server.py to open the port 65432 for listening (in first console) and then executing client.py to send a simple 'hello world' message (in a second console). This is what got printed to the first console:
Connected by ('127.0.0.1', 56051)
So far so good. Port 56051 connecting to port 65432, right? No.
I execute netstat -am (command tool utility to see state of sockets on the host machine) and found this:
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp4 0 0 127.0.0.1.51495 *.* LISTEN
Instead of 127.0.0.1.65432 as local address, it is using port 51495 instead.
Doing another verification check, this time firing off lsof -i -n:
COMMAND PID FD TYPE DEVICE SIZE/OFF NODE NAME
Code\x20H 51214 37u IPv4 0x1af15eb424ba89f3 0t0 TCP 127.0.0.1:51495 (LISTEN)
Both verifications confirmed that port 51495 is being used instead of 65432 as specified in my server.py and client.py scripts. Any leads or tips? Many thanks in advance!
65432 is the port number of your server socket, not your client socket. As the client end is not attached with any specific port number, it will be dynamically allocated with port number, every time you run the client code.
As far as I understood, you mentioned -
Connected by ('127.0.0.1', 56051)
is shown on the first console which is your server console. so this port number is port number of client socket. not the server socket.
In the server code, you are using, s.accept(), this function returns the connection temporary id and the address of the client which made the request. same thing you are trying to print in the code.
As #ottomeister pointed out, the process name was the first giveaway. The process name should have been Python but it showed VS Code instead, which is indicative that the port 51495 is opened by the VS Code process and has nothing to do with our socket module code.
The way the context manager was setup means that the connection will be closed the moment the last line (in this case, socket.sendall()) is executed. So the server socket is not active anymore.
I run netstat after the client socket has connected, by this point the server port is closed.
When I monitor the ports status while the server port is open (before the client socket connects with it) then sure enough 65432 is what appeared. This is confirmed in netstat, lsof and also nmap. A simple print statement after the socket connection is successful will also confirmed that the server port is in fact using the specified port number, which is 65432.
Sorry for the inconvenience, and again much appreciation to Ottomeister for first pointing this out.

Not able to read UDP packets on a server using Python

I'm trying to stream a video from a webcam installed on a BeagleBoneBlack (linux device) to a server (Windows server). The BeagleBone is connected to the Internet using DHCP (dynamic IP) and basically sends UDP packet to a server. On the server side I implemented a simple python program using sockets that should easily read UDP packet coming from a specific IP or on a specific port. In wireshark I'm able to see the packets arriving on the server but the python program is not able to catch them. I tried to listen on different IP such as 'localhost' or specific IP but nothing seems to work.
Python program server side:
import socket
IP = '192.168.23.240' #IP of the BeagleBone on Wireshark
IP = '109.164.170.155' #IP of the router in which the BeagleBone is attached
IP = '0.0.0.0' #localhost
IP = '' #localhost
IP = '192.168.0.21' #IP localhost server
IP = 'localhost' #localhost
PORT = 5454
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((IP,PORT))
f = open('file.mp4','wb')
data, addr = s.recvfrom(4096)
print 'Receiving from: ' +str(addr)
for i in xrange(1000):
f.write(data)
data, addr = s.recvfrom(4096)
print 'receiving from ' + str(addr) + ' ...'
f.close()
s.close()
In wireshark server side:
How is possible that I'm able to read the packets in wireshark but not using a simple python program? Someone know what am I doing wrong here?
If you run your program verbatim as you posted, it listens on localhost only, while your Wireshark screenshot suggests you're sending packets to "real" NIC with private IP address.
Are you sure your program does not work? When I fed it with netcat command like so:
cat myfile | nc -u 127.0.0.1 5454
it worked:
receiving from ('127.0.0.1', 38182) ...
receiving from ('127.0.0.1', 38182) ...
receiving from ('127.0.0.1', 38182) ...
Note I was sending from localhost to localhost. This reinforces hypothesis you have a simple network config/port configuration problem, not the Python program not working.
Do netstat -a on Windows machine to see if your program really listens on indicated address.
If it does, maybe your local Windows firewall blocks the connection? Can you try turning it off for a moment?

Can't perform TCP-handshake through a NAT between two NICs with SO_BINDTODEVICE

I'm trying to connect my computer to both sides of a NAT (run by OpenWRT) and to establish a TCP connection through the NAT:
I run a DHCP server on my first NIC (eth0, ip address 129.104.0.1) and connect it to the WAN port of the router (ip address 129.104.0.198)
I connect my wifi (wlan0, ip address 192.168.1.119) to the router's SSID behind the NAT
I'm using python and the SO_BINDTODEVICE option to send packet between a server (on eth0) and a client (on wlan0) through the NAT:
For the server:
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((str(self.local_ip_addr),self.handler.port))
self.server.setsockopt(socket.SOL_SOCKET,25,self.iface.name+"\0")
self.server.listen(10)
while self.stopped() is False:
connect = self.server.accept()[0]
connect.settimeout(1)
connect.close()
self.server.close()
For the client:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, 25, self.iface.name + "\0")
sock.settimeout(1)
try:
sock.connect((self.dest,self.handler.port))
sock.close()
expect socket.timeout, socket.error as e:
return -1
My problem is that the connection times out before. I wiresharked both my interfaces and it seems the problem resides on the client's side:
wlan0 sends a TCP SYN packet to 129.104.0.1
The packet is correctly NATed by the router and is received from 129.104.0.198 by eth0
eth0 replies with a SYN,ACK packet, which is correctly NATed back to wlan0
wlan0 does not understand this SYN,ACK and tries to retransmit the first SYN packet
I'm thinking it might have something to do with the linux-kernel refusing to receive a packet from an address that belongs to the machine but if anyone has a clue it would be of great help!
EDIT: I narrowed it down: it is indeed a kernel issue, the packets sent from eth0 are perceived as "martians" by the kernel because they have a local ip address as source. Setting net.ipv4.conf.all.accept_local=1 did not help, neither did deactivating net.ipv4.conf.all.rp_filter=0.
After browsing the kernel sources and adding a lot of KERNEL_WARNING we found where it came from: the linux kernel is configured on certain mainstream distributions (Ubuntu...) to act as a router and drop packets where the source address is suspect in order to prevent spoofing (search "rp_filter" on https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt and RFC3704).
To allow such traffic you have to set some variables on your machine (as root):
sysctl -w net.ipv4.conf.all.accept_local=1
sysctl -w net.ipv4.conf.all.rp_filter=0
sysctl -w net.ipv4.conf.your_nic.rp_filter=0
where your_nic is the network interface receiving the packet. Beware to change both net.ipv4.conf.all.rp_filter and net.ipv4.conf.your_nic.rp_filter, it will not work otherwise (the kernel defaults to the most restrictive setting).

Python network programming(bind to external address)

I am a newbie to python, and just few days back I started trying my hands on network programming(I am a newbie there too)
Now I found a neat client server program which was running quite simply on my computer, but when I replaced the local addresses, and told my friend to run the client script, it just wont respond.
My global I.P address : 120.59.XX.XXX
My Ipv4 address as returned by ipconfig : 192.168.1.2 (I am connected to internet through a router)
My gateway address : 192.168.1.1
Port used : 1060 (I tested this port locally and it wasn't in use)
#server.py
import socket
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
MAX = 65535
PORT = 1060
server.bind(('192.168.1.2', PORT))
print 'Listening at', server.getsockname()
while True:
data, address = server.recvfrom(MAX)
print 'The client at', address, 'says', repr(data)
server.sendto('Your data was %d bytes' % len(data), address)
Client Code :
#client.py
import socket
import sys
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
PORT = 1060
MAX = 65536
client.sendto('Hello Server!', ('120.59.XX.XXX', PORT))
data, address = client.recvfrom(MAX)
print 'The server', address, 'says', repr(data)
I started server.py on my computer and told my friend to start client.py, I allowed incoming connections to python through firewall, also I added 1060 port to windows incoming connections list.
Still it is not responding, and I am unable to decipher why(I have a dynamic IP address, but for the current session it remains constant and hence should work, also 1060 is a well known port and shouldn't be a problem right?)
You need to add a port forwarding rule in your router! something like from port 1060 forward to 192.168.1.2 port 1060.
You need a port-forward on the router, which would forward connections to router's external (global) address on port 1060 to your desktop IP 192.168.1.2 port 1060.

Categories

Resources