Presentation Layer

A layer that converts one data format to another so both the source and destination understand (Translates from one format to another and also called the translation layer). Sometimes, the presentation layer is not mentioned or used; this is because some of the previous functions are performed in the application layer. It depends on the protocol stack implementations.

This layer has different optional functions:


GNU ZIP (GZIP)

A compression technology that's commonly used for transferring data over the internet, it's based on the DEFLATE algorithm and its magic header is 1f 8b

To compress data using GZIP

from gzip import compress
compressed = compress(b"Test")
print("Output: {}\nHex: {}".format(compressed,compressed.hex(' ')))

Output

Output: b'\x1f\x8b\x08\x00\xc0\xc9\xc2f\x02\xff\x0bI-.\x01\x002\xd1Mx\x04\x00\x00\x00'
Hex: 1f 8b 08 00 c0 c9 c2 66 02 ff 0b 49 2d 2e 01 00 32 d1 4d 78 04 00 00 00

To decompress data using GZIP

from gzip import decompress
compressed = decompress(b'\x1f\x8b\x08\x00\xc0\xc9\xc2f\x02\xff\x0bI-.\x01\x002\xd1Mx\x04\x00\x00\x00')
print("Output: {}\nHex: {}".format(compressed,compressed.hex(' ')))

Output

Output: b'Test'
Hex: 54 65 73 74

PCAP Example

The client requested web content from the server and indicated that it accepts GZIP content, the server responds with content that is compressed in GZIP, the client receives the GZIP and gets handled in the presentation layer

Client Sends Data

The client uses the HTTP Accept-Encoding header to indicate that GZIP is allowed

Layer Protocol PDU Info Ports IPs MACs
Application Layer HTTP Data
  • GET / HTTP/1.1
  • Host: 10.0.0.2
  • User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
  • Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
  • Accept-Language: en-US,en;q=0.5
  • Accept-Encoding: gzip, deflate
  • Connection: keep-alive
  • Upgrade-Insecure-Requests: 1
Presentation Layer Raw Data GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1
Session Layer Socket Data GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1
Transport Layer TCP Segments GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1 Src Port: 35310
Dst Port: 80
Network Layer IP Packets GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1 Src Port: 35310
Dst Port: 80
Src IP: 10.0.0.3
Dst IP: 10.0.0.2
Data Link Layer Ethernet Frames GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1 Src Port: 35310
Dst Port: 80
Src IP: 10.0.0.3
Dst IP: 10.0.0.2

Src MAC: bc:35:db:cf:1b:03
Dst MAC: bc:f2:b8:57:86:02

Physical Layer Coax Bits 01001000 01010100 01010100 01010000 00101111 00110001 00101110 00110000 00100000  01001000 01010100 01001000 01010100 01001000 01010100

 

Server Receives Data

The server receives the client's HTTP Accept-Encoding request

Layer Protocol PDU Info Ports IPs MACs
Physical Layer Coax Bits 01001000 01010100 01010100 01010000 00101111 00110001 00101110 00110000 00100000  01001000 01010100 01001000 01010100 01001000 01010100
Data Link Layer Ethernet Frames GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1 Src Port: 35310
Dst Port: 80
Src IP: 10.0.0.3
Dst IP: 10.0.0.2

Src MAC: bc:35:db:cf:1b:03
Dst MAC: bc:f2:b8:57:86:02

Network Layer IP Packets GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1 Src Port: 35310
Dst Port: 80
Src IP: 10.0.0.3
Dst IP: 10.0.0.2
Transport Layer TCP Segments GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1 Src Port: 35310
Dst Port: 80
Session Layer Socket Data GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1
Presentation Layer Raw Data GET / HTTP/1.1\r\nHost: 10.0.0.2\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\nUpgrade-Insecure-Requests: 1
Application Layer HTTP Data
  • GET / HTTP/1.1
  • Host: 10.0.0.2
  • User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
  • Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
  • Accept-Language: en-US,en;q=0.5
  • Accept-Encoding: gzip, deflate
  • Connection: keep-alive
  • Upgrade-Insecure-Requests: 1

 

from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from io import BytesIO
from gzip import GzipFile
from datetime import datetime
from contextlib import suppress

with suppress(Exception):
    from netifaces import gateways, ifaddresses, AF_INET, AF_LINK
    print("The default network interface is: ",gateways()['default'][AF_INET][1])
    print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])

class Server(SimpleHTTPRequestHandler):
    def do_GET(self):
        compressed = False
        content = b'<HTML><h1>Hello World!</h1></HTML>'
        if len(content) > 0:
            if 'accept-encoding' in self.headers:
                if 'gzip' in self.headers['accept-encoding']:
                    bytes_ = BytesIO()
                    with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f:
                        f.write(content)
                        f.close()
                        content = bytes_.getvalue()
                        compressed = True
        self.send_response(200)
        if compressed:
            self.send_header('content-encoding', 'gzip')
        self.send_header('content-length', len(content))
        self.end_headers()
        self.wfile.write(content)

    def log_message(self, format, *args):
        print("[{}] - {}:{} - {} {}".format(datetime.now().strftime("%m/%d/%Y %H:%M:%S"), self.client_address[0],self.client_address[1],args[0],args[1]))

TCPServer(('0.0.0.0', 80), Server).serve_forever()

Server Sends Data

The server compresses and sends the compressed web content

Layer Protocol PDU Info Ports IPs MACs
Application Layer HTTP Data
  • HTTP/1.0 200 OK
  • Server: SimpleHTTP/0.6 Python/3.11.6
  • Date: Sun, 18 Aug 2024 02:54:42 GMT
  • content-encoding: gzip
  • content-length: 49

  • <HTML><h1>Hello World!</h1></HTML>
Presentation Layer GZIP Data HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"...
Session Layer Socket Data HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"...
Transport Layer TCP Segments HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"... Src Port: 80
Dst Port: 35310
Network Layer IP Packets HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"... Src Port: 80
Dst Port: 35310
Src IP: 10.0.0.2
Dst IP: 10.0.0.3
Data Link Layer Ethernet Frames HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"... Src Port: 80
Dst Port: 35310
Src IP: 10.0.0.2
Dst IP: 10.0.0.3
Src MAC: bc:f2:b8:57:86:02
Dst MAC: bc:35:db:cf:1b:03
Physical Layer Coax Bits 01001000 01010100 01010100 01010000 00101111 00110001 00101110 00110000 00100000  01001000 01010100 01001000 01010100 01001000 01010100

 

from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from io import BytesIO
from gzip import GzipFile
from datetime import datetime
from contextlib import suppress

with suppress(Exception):
    from netifaces import gateways, ifaddresses, AF_INET, AF_LINK
    print("The default network interface is: ",gateways()['default'][AF_INET][1])
    print("The default network interface mac address is: ",ifaddresses(gateways()['default'][AF_INET][1])[AF_LINK])

class Server(SimpleHTTPRequestHandler):
    def do_GET(self):
        compressed = False
        content = b'<HTML><h1>Hello World!</h1></HTML>'
        if len(content) > 0:
            if 'accept-encoding' in self.headers:
                if 'gzip' in self.headers['accept-encoding']:
                    bytes_ = BytesIO()
                    with GzipFile(fileobj=bytes_, mode='w', compresslevel=5) as f:
                        f.write(content)
                        f.close()
                        content = bytes_.getvalue()
                        compressed = True
        self.send_response(200)
        if compressed:
            self.send_header('content-encoding', 'gzip')
        self.send_header('content-length', len(content))
        self.end_headers()
        self.wfile.write(content)

    def log_message(self, format, *args):
        print("[{}] - {}:{} - {} {}".format(datetime.now().strftime("%m/%d/%Y %H:%M:%S"), self.client_address[0],self.client_address[1],args[0],args[1]))

TCPServer(('0.0.0.0', 80), Server).serve_forever()

Client Receives Data

Wireshark decompresses the content (The web browser does that as well in the background, and there will be a tab at the bottom that has the decompressed content)

Layer Protocol PDU Info Ports IPs MACs
Physical Layer Coax Bits 01001000 01010100 01010100 01010000 00101111 00110001 00101110 00110000 00100000  01001000 01010100 01001000 01010100 01001000 01010100
Data Link Layer Ethernet Frames HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"... Src Port: 80
Dst Port: 35310
Src IP: 10.0.0.2
Dst IP: 10.0.0.3
Src MAC: bc:f2:b8:57:86:02
Dst MAC: bc:35:db:cf:1b:03
Network Layer IP Packets HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"... Src Port: 80
Dst Port: 35310
Src IP: 10.0.0.2
Dst IP: 10.0.0.3
Transport Layer TCP Segments HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"... Src Port: 80
Dst Port: 35310
Session Layer Socket Data HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"...
Presentation Layer GZIP Data HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.11.6\r\nDate: Sun, 18 Aug 2024 02:54:42 GMT\r\ncontent-encoding: gzip\r\ncontent-length: 49\r\n\r\n....rb.f..........0..H...W../.IQ........g..7"...
Application Layer HTTP Data
  • HTTP/1.0 200 OK
  • Server: SimpleHTTP/0.6 Python/3.11.6
  • Date: Sun, 18 Aug 2024 02:54:42 GMT
  • content-encoding: gzip
  • content-length: 49

  • <HTML><h1>Hello World!</h1></HTML>