I have a raspberry pi that is both connected to the internet via Wlan and a local device via Ethernet. So it has two IPs; one for each endpoint.
This is how it looks like simplified when running ifconfig; with different IPs for privacy
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 189.168.200.110 netmask 0.0.0.0 broadcast 255.255.255.255
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 189.168.201.79 netmask 255.255.255.0 broadcast 192.168.1.255
This is the code that python is using to send a message to the device through the Ethernet with that gateway's ip
TCP_PORT = 3001
SERVER_IP_AD = "189.168.200.110"
CLIENT_IP_AD = "189.168.200.155"
BROADCAST_IP = "255.255.255.255"
def sendMessage(self, file_path, client_ip=CLIENT_IP_AD):
print('message en route')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((self.SERVER_IP_AD, 0))
s.connect((client_ip, self.TCP_PORT)) #**ERROR IS HERE**
MESSAGE = self.openFile(file_path)
s.send(MESSAGE.encode())
data = s.recv(self.BUFFER_SIZE)
s.close()
return data
Using wireshark I can see that the package is being sent through the Wlan interface instead of the Ethernet interface with the correct IP source and IP destination.
How do I tell python to use the correct interface when sending out the package?
In my opinion, you can establish Tcp connection with Ethernet, cause there isn't shaking hands by Ethernet
And, you shouldn't use s.bind() and s.connect() at the same time. Because the former is for UDP client, and the later is for TCP client. Have a try with only s.bind().
Related
I am trying to send message from Raspberry Pi (Ubuntu 20) to Laptop (Virtualbox Ubuntu 20) via UDP socket. So I am using simple code from https://wiki.python.org/moin/UdpCommunication
Sending (from Raspberry Pi)
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
MESSAGE = b"Hello, World!"
print("UDP target IP: %s" % UDP_IP)
print("UDP target port: %s" % UDP_PORT)
print("message: %s" % MESSAGE)
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
Receiving (from laptop)
import socket
UDP_IP = "127.0.0.1"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print("received message: %s" % data)
I tried UDP_IP = "0.0.0.0" in both ends.
I tried Ip address of my laptop at RPI end.
I tried both machine's IP address at both ends.
I tried sock.bind(("", UDP_PORT)) to bind all.
I tried adding the UDP port number in firewall settings.
I checked multiple questions from this forum related to this.
Still, I cannot get any packets at the laptop receiving side. I do not know what is wrong.
Please advise.
The problem may be in the IP address because you are using the IP '127.0.0.1' (localhost) to reach an outside device. Please find out the IPs of your devices, try using ifconfig Linux command. Also, check that nothing is blocking your connection.
Consider that for socket.bind(address) you can use '0.0.0.0' and for socket.sendto(bytes, address) you should use the IP of the device you want to send to.
I recommend you to download a program called Hercules, with this program you can create a UDP peer to figure out what is not working properly. For example, you could use python in one side and Hercules in the other to rule out mistakes in one side of the code execution, you could also try two Hercules connections and see if you can establish communication in which case the problem is most likely related to the code execution, in the other hand if you can not establish a connection between the two Hercules UDP peers the problem is most likely with the devices or the network itself.
If you are using a static IP on the RPi, you need to add a static route:
sudo ip route add 236.0.0.0/8 dev eth0
Make sure the port you are using have UDP enabled in windows 10.
To open any UDP ports, you can do the following:
Go to Control Panel> System and Security and Windows Firewall.
Advanced settings > right-click Inbound Rules and select New Rule.
Add the port(s) you want to open and click Next.
Select UDP protocol and the port(s) number(s) into the next window
and click Next.
Select Allow the connection and hit Next.
Select the network type and click Next.
Give a name for the rule and click Finish.
I'm experimenting testing with multicast and I have a couple questions of how I can accomplish this.
First, is it absolutely necessary for me to have a router to accomplish multicast if the two systems are under the same subnet (i.e 10.10.1.10 and 10.10.1.12) or can I just have a switch or even point to point connection? I would say no because of some of the tests I've ran, but it'd be nice to know for sure.
Second, how can I set up, if at all possible, a multicast connection between my Windows 10 PC and a VMWare running CentOS7 on that same PC?
What I have right now:
A VMWare with a bridged network to my External Connection and running CentOS7.
The VM has an IP of 10.10.1.12 and a netmask of 255.255.255.0 and the windows has a IP of 10.10.1.10 and a netmask of 255.255.255.0.
I've written a receive python script based on a something I've found running on the VM
import socket
import struct
MCAST_GRP = '224.0.0.71'
MCAST_PORT = 1000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
print sock.recv(10240)
and a sending python script from my host PC
import socket
MCAST_GRP = '224.0.0.71'
MCAST_PORT = 1000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
sock.sendto("robot", (MCAST_GRP, MCAST_PORT))
on my CentOS7 VM I can see the receive script is signing up to the group by running
netstat -g
I can also see the incoming packets by running
sudo tcpdump -i <NIC> host 224.0.0.0/4
which shows
14:28:03.111837 IP 10.10.1.101.60007 > 224.0.0.71.cadlock2: UDP, length 26
I can also see it in Wireshark as an incoming UDP message, but my python receive script running isn't receiving it.
I've also set net.ipv4.all.rp_filter to 0 that I've seen while doing research, but nothing.
However, I can run the send and receive scripts on the Windows PC and receive them just fine. I can even see them in Wireshark and they show up as IP 10.10.1.101 to 224.0.0.71 IPV4mcast.
I can also send messages from the VM to the host PC just fine. I just can't receive on the VM.
I need to send a UDP packet over ethernet from 169.254.xx.xx to 192.168.xx.xx. The second address is the address of the FPGA and its MAC address is known. I am using wireshark to monitor the packets, but when i have an unbound socket, and I call sock.sendto() it sends over WLAN. When I bind the socket to the WLAN interface, it sends, but when I bind the socket to the ethernet interface, I get this error when I try to send:
OSError: [WinError 10051] A socket operation was attempted to an unreachable network
When bound to the ethernet interface, and i send to an unused address in the 169.254.xx.xx subnet, it sends an ARP, but nothing is sent when the destination is in the 192.168.xx.xx subnet.
Here is the code:
import socket
import time
address = '192.168.1.239'
port = 1235
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('169.254.190.73', 0))
sock.sendto('100'.encode('utf-8'), (bytes(address, 'UTF-8'), port))
time.sleep(0.005)
sock.close()
'''
'''
Since 169.254.xx.xx and 192.168.xx.xx represent different networks, traffic in between needs to be routed. However, 169.254.0.0/16 (autoconf) isn't usually routed.
If both nodes actually reside in the same layer 2 segment, just (manually) change the autoconf client's IP address.
Today, I have made my very first sockets program - I made a client and a server that message each other (kind of like a chat) using sockets. When using the internal IP as 'host', The connection is established, otherwise using the external IP, no connection is established.
Edit 1:
#Client
s = socket.socket()
host = '123.123.123.123'
port = 9999
s.connect((host, port))
#Server
host = ''
port = 9999
s = socket.socket()
s.bind((host, port))
s.listen(5)
connection, address = s.accept()
How will this work properly with, for example, a laptop? Since your IP changes each time you switch Wifi, how would I be able to create a program that would permanently work with this specific laptop?
I understand that I have to port-forward the specific port to a specific internal machine such as 192.168.0.5. but what if I'm using a laptop and I don't have access to the WIFI router. I wouldn't have access to every router a laptop uses.
I want the code to be permanently compatible.
Use DynDNS.com or NoIP.com portal. You install program on laptop which check your IP frequencly and sends current IP to portal which assigns this IP to your address like "my_laptop.noip.com". Then people can access your laptop using "my_laptop.noip.com" instead of IP address.
You always assign socket to IP of local network card (NIC) like WiFi. You can't assing to external IP. You have to config your router so requests to external IP:port will be send to your local IP:port. Of course Internet Provider routers can block your ports and it will not work.
tcmpdump can view all the multicast traffic to specific group and port on eth2, but my Python program cannot. The Python program, running on Ubuntu 12.04:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Multicast port is 52122
sock.bind(('', 52122))
# Interface eth2 IP is 1.2.3.4, multicast group is 6.7.8.9
mreq = socket.inet_aton('6.7.8.9')+socket.inet_aton('1.2.3.4')
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
print '\nwaiting to receive message'
data, address = sock.recvfrom(1024)
print data
When I use another program to send a multicast packet to eth2, it works and prints the packet. But it fails to see all the current multicast traffic. If I run tcpdump on eth2 on the same port and group as the above program:
sudo tcpdump -i eth2 host 6.7.8.9 and port 52122
it sees both the packets I send from another program AND all the current multicast traffic. It's output looks likes this...
# Packet sent from my other program
09:52:51.952714 IP 1.2.3.4.57940 > 6.7.8.9.52122: UDP, length 19
# Packet send from the outside world
09:52:52.143339 IP 9.9.9.9.39295 > 6.7.8.9.52122: UDP, length 62
Why can't my program see the packets from the outside world? How can I modify it (or something else) to fix this?
Edit:
I should have mentioned, the interface this going over is not eth2 but eth2.200 a VLAN. (The local IP and the tcpdump commands are all run with eth2.200, I just changed that in this question to make it simpler.) Based on this answer that could be the problem?
Edit #2:
netstat -ng when the program is running shows eth2.200 subscribed to 224.0.0.1 and 6.7.8.9`.
tshark -i eth2.200 igmp shows three repeated 1.2.3.4 -> 6.7.8.9 IGMP 46 V2 Membership Report / Join group 6.7.8.9 when the program first starts. When the program process is killed, it shows 1.2.3.4 -> 224.0.0.2 IGMP 46 V2 Leave group 6.7.8.9. There is also an infrequent 1.2.3.1 -> 224.0.0.1 IGMP 60 V2 Membership Query, general, where 1.2.3.1 is 1.2.3.4's gateway.
Not sure if it will help, but the routing table looks like:
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 1.2.5.6 0.0.0.0 UG 0 0 0 eth1
1.2.3.0 0.0.0.0 255.255.255.240 U 0 0 0 eth2.200
Thank you!
Finally! Found this question on ServerFault that addresses the same thing. Basically the kernel was not forwarding on / was filtering out the packets because it thought the sourced address was spoofed.
Changed the settings in /etc/sysctl.conf to match:
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.ip_forward = 1
Rebooted and everything works.