@doctorow, a tiny little comment.
Intrinsic to core Internet protocols like IPv4/6, TCP and UDP is the potential to “tunnel” one protocol inside another.
More generally, if you have any way to get bidirectional communication, you can use it to tunnel IP packets through (and with them all the TCP/UDP/ICMP/whatever that IP can hold).
A packet is a block of data with header and payload (and sometimes checksum at the end). Encapsulating packets in different-type packets is the bread and butter of networks; Ethernet hardware cannot handle anything but Ethernet frames, so IP packets are encapsulated to such frames, and target address is obtained via ARP protocol that serves to map MAC addresses (which identify the network cards) to IP addresses (which are assigned to the computers). The Ethernet frame then has the IP packet as its payload. On reception by the network card hardware, it is fed to the operating system’s kernel, where it is stripped of the frame’s headers and the payload is fed to the IP stack. (Or IPX stack, or other, if non-IP protocol is used.)
Same applies for TCP, UDP, ICMP, and the less known sub-protocols that are the payload of the raw IP packets.
You can have a direct LAN-to-LAN tunnel, acting as if the networks were connected with a cable, by putting the whole ethernet frames as payloads to (say) UDP packets, sending them through the Net, and then on the other side the raw frames can be fed to the Ethernet network.
Same for IP packets; they can be encapsulated in e.g. UDP with ease. (So, on the “wire”, you get
(Ethernet header (IP header (UDP header (tunneled IP header (TCP or UDP header, whatever we are sending (data themselves) )))))
Same way we can tunnel IP through anything higher-level. There are existing programs for tunneling through ICMP, or even DNS. And others can be written on demand, as the situation requires; the availability of a lot of opensource network utilities provides us with a wide palette of almost-there prefab solutions for many needs.
Anything can be tunneled through anything. Even if we have nothing but ASCII chat, we still can send base64 encoded raw packets back and forth. The latencies and bandwidth will be crap but that is the cost of such approach.
Then there’s steganography, where we dilute the important data in some cover data. A low-bandwidth binary channel can be hidden in e.g. a video chat that way. Wasteful, but fairly difficult to discover, especially at low ratio of covert data to overt data. We are used to SMS messages; these 160-character morsels of text are small enough to be hidden in almost anything and are proven to be sufficient for many communication needs.
TL;DR version: any protocol[1] can be tunneled through any bidirectional communication channel. Also, a sufficiently narrow-bandwidth covert channel can be hidden in a sufficiently wide-bandwidth overt channel.
[1] Within the limits of available bandwidth and speed.