Foundations of Python Network Programming

(WallPaper) #1

Chapter 2 ■ UDp


32


One last warning is in order. Since the foregoing discussion indicated that binding your server to the interface
127.0.0.1 protects you from possibly malicious packets generated on the external network, you might think that
binding to one external interface will protect you from malicious packets generated by malcontents on other external
networks. For example, on a large server with multiple network cards, you might be tempted to bind to a private
subnet that faces your other servers and think therefore that you will avoid spoofed packets arriving at your
Internet-facing public IP address.
Sadly, life is not so simple. It actually depends on your choice of operating system and how it is configured
whether inbound packets addressed to one interface are allowed to arrive at another interface. It might be that your
system will quite happily accept packets that claim to be from other servers on your network if they appear over your
public Internet connection! Check with your operating system documentation, or your system administrator, to find
out more about your particular case. Configuring and running a firewall on your box could also provide protection if
your operating system does not.


UDP Fragmentation


I have been speaking so far in this chapter as though UDP lets you, as a user, send raw datagrams that are simply
packaged up as IP packets with just a little bit of additional information—a port for both the sender and receiver. But
you might already have become suspicious because the foregoing program listings have suggested that a UDP packet
can be up to 64kB in size, whereas you probably already know that your Ethernet or wireless card can only handle
packets of around 1,500 bytes instead.
The actual truth is that while UDP does send small datagrams as single IP packets, it has to split larger UDP
datagrams into several small IP packets so that they can traverse the network (as was briefly discussed in Chapter 1).
This means that large packets are more likely to be dropped, since if any one of their pieces fails to make its way to the
destination, then the whole packet can never be reassembled and delivered to the listening operating system.
Except for the higher chance of failure, this process of fragmenting large UDP packets so that they will fit on the
wire should be invisible to your application. There are three ways, however, in which it might be relevant.


•    If you are thinking about efficiency, you might want to limit your protocol to small packets
to make retransmission less likely and to limit how long it takes the remote IP stack to
reassemble your UDP packet and give it to the waiting application.

•    If the ICMP packets are wrongfully blocked by a firewall that would normally allow your
host to autodetect the MTU between you and the remote host (a common situation in the
late 1990s), then your larger UDP packets might disappear into oblivion without your ever
knowing. The MTU is the “maximum transmission unit” or “largest packet size” that all of the
network devices between two hosts will support.

If your protocol can make its own choices about how it splits up data between different datagrams and you want
to be able to auto-adjust this size based on the actual MTU between two hosts, then some operating systems let you
turn off fragmentation and receive an error if a UDP packet is too big. You could then be careful to fashion datagrams
that fall under the minimum unit.
Linux is one operating system that supports this last option. Take a look at Listing 2-3, which sends a large
datagram.


Listing 2-3. Sending a Large UDP Packet


#!/usr/bin/env python3


Foundations of Python Network Programming, Third Edition


https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter02/big_sender.py


Send a big UDP datagram to learn the MTU of the network path.


import IN, argparse, socket

Free download pdf