Network protocols with Ruby
I’m a fan of network communications and computer security, and I will publish a set of articles to understand basic networking concepts that could be useful to attack network protocols.
This is a personal project with non-profit purposes, just to have fun and learn about Networking, Security, Ruby. I hope you enjoy reading this and learn with me.
I will use the Ruby programming language and the bundler tool to install examples dependencies.
Let’s start defining basic concepts.
What is a network?
A network is a set of 2 or more device connected together sharing information. Example:
We can see four devices with different operating systems connected to the same network, where they communicate and share data using common network protocols.
What is a network protocol?
A network protocol is defined by a set of rules that help to establish communication between multiple hardware devices running different operating systems with its own communication stack.
A network protocol is used for:
- Keep session state.
- Identifying nodes by addressing.
- Controlling the transmission flow.
- Ensuring the order of the transmitted data.
- Detecting an correcting errors.
- Formatting and encoding data.
The Internet Protocol Suite (IPS)
The Internet protocol suite, commonly known as TCP/IP, is the set of communications protocols used in the Internet and similar computer networks. The current foundational protocols in the suite are the Transmission Control Protocol (TCP) and the Internet Protocol (IP), as well as the User Datagram Protocol (UDP).
Network protocols send network traffic over internet using the following protocol stack with 4 layers:
- Link layer: This is the lowest level and describes the physical mechanism used to transfer information between the devices on a local network.
- Internet layer: This layer provides the mechanisms for addressing network devices. The devices don’t need to be on the local network. This level contains the IP which could be IPv4 or IPv6.
- Transport layer: This layer is responsible for connections between clients and servers, sometimes ensuring the correct order of packets and providing a service multiplexing. TCP and UDP protocols operate at this layer.
- Application layer: This layer contains network protocols such as HTTP, DNS, SMTP, MongoDB, SSH, etc.
Each layer interacts only with the layer above and below it, there must be some external interactions in the stack. The link layer interacts with physical network connection, transmitting data in physical medium, such as pulses of electricity or light and the application layer interacts with the user application.
Data encapsulation
The IPS is composed of multiple layers, each of which is constructed upon the one above it and is capable of encapsulating data from the layer above to allow for layer-to-layer communication. Each layer’s data transmission is referred to as a protocol data unit (PDU).
Headers, Footers and Addresses
The PDU in each layer contains the payload that is being transmitted. it’s a common to prefix a header – which contains information required for the payload data to be transmitted, such as source and destination address in the network. Sometimes a PDU also has a footer that is suffixed to the payload data and contains values needed to ensure correct transmission, such as error checking information.
-
The application layer contains the payload specific for the content parser of the application that will read this data, and this can be clear text, binary or encrypted data.
-
The transport layer contains a TCP/UDP header with the source and destination port number. These port numbers allow a single device to have multiple unique network connections and they range from 0 to 65535. The TCP payload and header are commonly called a segment, whereas a UDP payload and header are commonly called a datagram.
-
The Internet layer has an IP payload with header that includes a source and a destination address. The destination address allows the data to be sent to a specific device on the network. The source address allows the receiver of the data to know which node sent the data and allows the receiver to reply to the sender. An IP payload and header are commonly called a packet.
-
The Link layer has the ethernet payload with a source and destination addresses. Ethernet uses a 64-bit value called a Media Access Control (MAC) address, which is typically set during manufacture of the Ethernet adapter. The MAC addresses are written as a series of hexadecimal numbers separated by dashes or colons, example: 24:E5:D9:2F:3D:4C. The Ethernet payload, including the header and footer is referred to as a frame.
Example
There was too much theory there, so let’s examine the data encapsulation layer in a real network communication between two computers by starting with a simple example.
In the following example we will capture and display the network communications between the ftp client and a public anonymous FTP server.
Sniffer
To capture and display the network traffic we will require a simple sniffer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require 'packetfu'
include PacketFu
iface = ARGV[0] || PacketFu::Utils.default_int
filter = 'host ftp.netbsd.org and tcp and port 21'
cap = Capture.new(iface: iface, start: true, filter: filter)
puts "Capturing network traffic..."
cap.stream.each do |p|
pkt = Packet.parse(p)
next unless pkt.is_ip?
next if pkt.ip_saddr == Utils.ifconfig(iface)[:ip_saddr]
packet_info = [pkt.ip_saddr, pkt.ip_daddr, pkt.size, pkt.proto.last]
puts '=' * 80
puts "%-15s -> %-15s %-4d %s" % packet_info
puts pkt.dissect
puts ""
end
NOTE: You can comment or remove the line 13 if you want observe all the packets from the client and the server.
FTP client
To generate the traffic we will use a very simple ftp client.
1
2
3
4
5
6
7
8
9
10
require 'net/ftp'
host = 'ftp.netbsd.org'
ftp = Net::FTP.new(host, debug_mode: true)
ftp.login('anonymous')
ftp.chdir('pub')
ftp.list('*').each do |f|
puts f
end
ftp.close()
Demo
Executed commands
1
2
3
bundle install
rvmsudo bundle exec ruby sniffer.rb
bundle exec ruby ftp_client.rb
Ouput examples
In the output of the sniffer there can be observed the 4 layer of encapsulation per packet, for example:
TCP Handshake packet
This packet contains the Link (EthHeader), Internet (IPHeader), and Transport (TCPHeader) layers because it is part of the TCP protocol handshake, for example the A and S flags can be seen in the TCPHeader and this does not include anything related the application layer, which means the application payload is empty.
FTP server response (Packet with application payload)
This packet that includes the Link (EthHeader), Internet (IPHeader), Transport (TCPHeader) and Application layers because it presents the server’s initial response via the FTP protocol.In this case, the payload is in clear text, and the ftp client can understand it.
You can get the same results with tools like wireshark, tshark or tcpdump but it is very easy implementing this with Ruby.
Routing, host name resolution (dns), protocol analysis, protocol implementation, and other topics were not covered here and will be covered in subsequent posts.
Happy Friday everyone!