I am using Python to send UDP packets to an FPGA board and am fairly new to python. I am using wireshark to monitor the packets being sent and I know the the FPGA is receiving all the packets correctly. The problem is with what packets are being sent. The computer does not recognize what the FPGA is when it is connected so it leaves it as an unidentified network and assigns it an IP address (169.254.233.200). I am using this code to try and send a UDP packet that simply says "Test" to the FPGA (Sorry for the terrible formatting).
import sys
import socket
def main():
UDP_IP="169.254.233.201"
UDP_PORT=9
MESSAGE='Test'
print ("UDP target IP:", UDP_IP)
print ("UDP target port:", UDP_PORT)
print ("message:", MESSAGE)
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) # UDP
sock.sendto( bytes(MESSAGE, 'UTF-8'), (bytes(UDP_IP, 'UTF-8'), UDP_PORT) )
However, instead of sending a UDP packet when this script is run, the computer broadcasts a message saying "Who has 169.254.233.201? Tell 169.254.233.200". I'm guessing this a problem caused by the unidentified network, or I am just addressing the packet incorrectly. I am trying to keep the HDL on the FPGA as simple as possible, so I would prefer if it didn't have to send any packets to the computer to verify the connection. This is why I wanted to use UDP over TCP.
Any Help would be appreciated.
Graeme
SOLVED: I noticed that the computer was sending messages to port 169.254.255.255 when trying to set up the connection. I changed UDP_IP="169.254.233.201" to UDP_IP="169.254.255.255" and the UDP packets started going through.
LESSON: I am bad at IP addresses.
For the reference/future readers, the problem was the your FPGA lacks the ARP protocol support.
The Ethernet frames cannot be sent directly to IP address, only to the MAC address. Thus, the sender computer must somehow learn IP<->MAC address mapping. Normally, the "ARP" protocol does that -- the message "Who has 169.254.233.201? Tell 169.254.233.200". is ARP request.
The proper workaround is to add ARP entry manually, for example on Linux, one would write arp -s 169.254.233.201 00:00:11:22:33:44 to tell computer the MAC address of the FPGA board. Even better way is to teach FPGA board to respond with proper ARP reply.
The address 169.254.255.255 is a "broadcast address", which goes to all computers at once (hence no need for ARP). This is OK to use for testing, but if you were to put it to large network and send a lot of traffic, then this traffic will be received by every computer on the network (i.e. it will drain battery on your ipad faster if you put it on home network)
Related
So I'm trying to build a packet sniffer in Python to deepen my understanding of networking. Thing is, it has turned out to be a tad bit more confusing than I initially anticipated. The problem is that all resources with thorough explanations cover the scenario of creating sockets for client/server data sending/receiving purposes.
At this point, I've successfully created some classes that handle packet header decoding for IPv4 and ICMP. Now, since my socket code only seemed to capture ICMP packets, I've been trying to configure it so that I can catch all traffic reaching my wifi interface, but I still almost exclusively see ICMP packets (with localhost as both source and destination).
So, I have some questions which I'd like to get answered. But first, my code:
import socket
import sys
from protocols.ipv4 import IPv4
PACKET_SIZE = 65535
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
sock.bind(("0.0.0.0", 0))
try:
while True:
# read in a packet
raw_buffer = sock.recvfrom(PACKET_SIZE)[0]
# create an IP packet object
ip_header = IPv4(raw_buffer)
# print the packet
print(ip_header)
except KeyboardInterrupt:
print("\nExiting...")
sock.close()
sys.exit(0)
This is how I've understood it:
First I'm creating a socket with socket.socket, where I specify address family, socket type and protocol. In my case, I'm selecting the AF_INET family which I don't really understand very well, but it seems to yield packets from the network layer. The socket type is set to SOCK_RAW meaning that I want the raw sockets as opposed to using SOCK_STREAM for TCP connections and SOCK_DGRAM for UDP. The last argument IPPROTO_IP just indicates that I want IP packets only.
Then, I'm binding the socket to 0.0.0.0 which supposedly means "any address" as described here.
What I don't understand:
Initially, I saw some examples of creating a sniffer socket which used the AF_PACKET address family. I soon found out that this address family is not available on macos (which I'm using). Why is that? What is an address family how does it relate to sockets? Is there an alternative way to catch packets from lower levels? In Wireshark I can see ethernet datagrams, so it seems possible.
As I've stated, I want to sniff all the traffic reaching my wifi interface. How does the socket know which interface I want it to operate on? Also I've learned that network interfaces can be put into different modes like monitor or promiscuous, how does that relate to sockets and my goal of catching packets?
Why am I almost only catching ICMP packets? What is the purpose of these packets with localhost both as destination and source?
I know there are lots of gaps in my current understanding of this. I'm not sure if I'll be able to get this to work, but I'm curious and I'd be grateful for any kind of answer or even just some good resources to check out.
Edit: My main question is where can I find out more about sockets in the context of packet sniffing?
If a socket program runs on a port(say 6053) and if the rule is not added in the firewall the functions recv read and recvfrom are blocked.
How do we check this in C or python and report Port not opened error on linux machines.
Try to connect on that port using socket.connect(), if connection is not successful, then show message that Port not opened.
Tools like nmap can help in determining whether the particular port is open or closed.
TCP :
nmap uses techniques like TCP SYN scan or TCP Connect scan where the server will reply with ACK-RST packet for SYN request incase of closed port. You can notice that, it is determined at the time of 3-way handshake (connection establishment) itself.
UDP : nmap also facilitates the UDP scan, where ICMP based 'Port Unreachable' packet shall be returned in case the UDP packet arrives on a closed UDP port (This also depends on the stack in the OS). Unlike TCP, the UDP is not a connection-based protocol and ICMP is also connection-less, so you might need to send some significant number of UDP packets for a short interval and evaluate based on the responses or some similar logic.
You can arrive on similar technique/logic and determine whether the particular port is open or closed and flash appropriate message for user.
I have a client written using python-twisted (http://pastebin.com/X7UYYLWJ) which sends a UDP packet to a UDP Server written in C using libuv. When the client sends a packet to the server, it is successfully received by the server and it sends a response back to the python client. But the client not receiving any response, what could be the reason ?
Unfortunately for you, there are many possibilities.
Your code uses connect to set up a "connected UDP" socket. Connected UDP sockets filter the packets they receive. If packets are received from any address other than the one to which the socket is connected, they are dropped. It may be that the server sends its responses from a different address than you've connected to (perhaps it uses another port or perhaps it is multi-homed and uses a different IP).
Another possibility is that a NAT device is blocking the return packets. UDP NAT hole punching has come a long way but it's still not perfect. It could be that the server's response arrives at the NAT device and gets discarded or misrouted.
Related to this is the possibility that an intentionally configured firewall is blocking the return packets.
Another possibility is that the packets are simply lost. UDP is not a reliable protocol. A congested router, faulty networking gear, or various other esoteric (often transient) concerns might be resulting in the packet getting dropped at some point, instead of forwarded to the next hop.
Your first step in debugging this should be to make your application as permissive as possible. Get rid of the use of connected UDP so that all packets that make it to your process get delivered to your application code.
If that doesn't help, use tcpdump or wireshark or a similar tool to determine if the packets make it to your computer at all. If they do but your application isn't seeing them, look for a local firewall configuration that might reject them.
If they're not making it to your computer, see if they make it to your router. Use whatever diagnostic tools are available (along the lines of tcpdump) on your router to see whether packets make it that far or not. Or if there are no such tools, remove the router from the equation. If you see packets making it to your router but no further, look for firewall or NAT configuration issues there.
If packets don't make it as far as your router, move to the next hop you have access to. This is where things might get difficult since you may not have access to the next hop or the next hop might be the server (with many intervening hops - which you have to just hope are all working).
Does the server actually generate a reply? What addressing information is on that reply? Does it match the client's expectations? Does it get dropped at the server's outgoing interface because of congestion or a firewall?
Hopefully you'll discover something interesting at one of these steps and be able to fix the problem.
I had a similar problem. The problem was windows firewall. In firewall allowed programs settings, allowing the communication for pythonw/python did solve the problem. My python program was:
from socket import *
import time
address = ( '192.168.1.104', 42) #Defind who you are talking to (must match arduino IP and port)
client_socket = socket(AF_INET, SOCK_DGRAM) #Set Up the Socket
client_socket.bind(('', 45)) # arduino sending to port 45
client_socket.settimeout(1) #only wait 1 second for a response
data = "xyz"
client_socket.sendto(data, address)
try:
rec_data, addr = client_socket.recvfrom(2048) #Read response from arduino
print rec_data #Print the response from Arduino
except:
pass
while(1):
pass
I'm having trouble receiving a UDP packet sent from an FPGA in a python program. I've checked similar questions and did the following:
Checked that Wireshark can the see UDP packet
Disabled windows firewall in PC
Used sock.bind() since it's UDP packets
Manually set the destination MAC address on Ethernet frame since FPGA does not support ARP
Set dest IP to broadcast 10.10.255.255 for testing, no packets received
Set the UDP checksum of the packet from the sender to 0x0000
Here's the python receiver code:
import socket
import sys
UDP_IP = "10.10.10.87"
UDP_PORT = 4660
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
print("Socket: "+str(sock.getsockname()))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print(data)
print(addr)
sys.stdout.flush()
When tested against another python script that sends to 10.10.10.87:4660
(from another PC in the 10.10.10 network) the receiver script works fine. I've even tried to recreate the UDP pcket byte-by-byte in the FPGA from packets that I know are received OK (Differences are source IP, port & MAC, checksums (disabled), identification).
Here's the output for both packets from Wireshark:
Wireshark UDP packet (Python UDP packet that gets received OK on the left, Xilinx FPGA packet that is not received by python on the right)
I'm not sure what else to try. Any help would be appreciated.
Apparently the IPv4 header checksum from an FPGA calculation was wrong. It can get confusing to follow since the TTL (Time to Live) changes on a router hop, and the new TTL will also change the IPv4 header, forcing a new checksum per hop until it gets to Wireshark on the receiver end. By default Wireshark has IPv4 checksum validation disabled (as can be seen in the question screenshot), the answer is easier to spot with validation on.
I set the IPv4 checksum during packet construction to zero (x0000). It gets recalculated correctly at the router, and with the correct checksum Python can receive the packet.
I also tested a direct connection (without router) from the FPGA to the host PC. The IPv4 header also gets recalculated correctly (I'm not sure where, probably the PC's NIC?)
Hope this is useful to someone with similar problems.
I have a client-server "snake" game working really well with TCP connections, and I would like to try it the UDP way.
I wonder how it is supposed to be used ? I know how UDP works, how to make a simple ECHO example, but I wonder how to do the following :
For instance with TCP, every TICK (1/15 second) server sends to the client the new Snake head position.
With UDP, am I supposed to do something like this :
Client SIDE :
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
serverAddr = (('localhost', PORT))
while 1:
client.sendto('askForNewHead', serverAddr)
msg, addrServer = client.recvfrom(1024)
game.addPosition(msg)
Server SIDE :
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind((HOST, PORT))
while 1:
data, addr = server.recvfrom(1024)
server.sendto(headPosition, addr)
So here Client has to ask server to get the new head position, and then server sends the answer. I managed to make it work this way, but I can't figure out if it is a good way of doing.
Seems weird that client has to ask udp for an update while with my TCP connection, client has just to wait untill he receives a message.
There are differences between TCP and UDP but not the way you describe. Like with TCP the client can recvfrom to get messages from the server without asking each time for new data. The differences are:
With TCP the initial connect includes a packet exchange between client and server. Unless the client socket was already bound to an IP and port it will be bound to the clients IP and a free port will be allocated. Because of the handshake between client and server the server knows where to contact the client and thus can send data to the packet without getting data from the client before.
With UDP there is no initial handshake. Unless already bound, the socket will be bound to clients IP and a free port when sending the first packet to the server. Only when receiving this packet the server knows the IP and port of the client and can send data back.
Which means, that you don't need to 'askForNewHead' all the time. Instead the client has to send only a single packet to the server so that the server knows where to send all future packets.
But there are other important differences between TCP and UDP:
With UDP packets may be lost or could arrive in a different order. With TCP you have a guaranteed delivery.
With UDP there is no real connection, only an exchange of packets between two peers. With TCP you have the start and end of a connection. This is relevant for packet filters in firewalls or router, which often need to maintain the state of a connection. Because UDP has no end-of-connection the packet filters will just use a simple timeout, often as low as 30 seconds. Thus, if the client is inside a home network and waits passively for data from server, it might wait forever if the packet filter closed the state because of the timeout. To work around this data have to be transmitted in regular intervals so that the state does not time out.
One often finds the argument, that UDP is faster then TCP. This is plain wrong. But you might see latency problems if packets get lost because TCP will notice packet loss and send the packet again and also reduce wire speed to loose less packets. With UDP instead you have to deal with the packet loss and other congestion problems yourself. There are situations like real time audio, where it is ok to loose some packets but low latency is important. These are situations where UDP is good, but in most other situations TCP is better.
UDP is different to TCP, and I believe with python the client does have to ask for an update from the server.
Although it is fun to learn and use a different way of communicating over the internet, for python I would really recommend sticking with TCP.
You don't have to ask the server for a update. But since UDP is connection-less the server can send head-positions without being asked. But the client should send i'm-alive-packets to the server, but this could happen every 10 seconds or so.