Operating Systems Azure

Debian 13 Networking Tools on Azure User Guide

| Product: Debian 13 Networking Tools on Azure

Overview

This guide covers the deployment and configuration of Debian 13 Networking Tools on Microsoft Azure using cloudimg's pre configured virtual machine image from the Azure Marketplace.

Debian is one of the oldest and most widely deployed Linux distributions, built by a volunteer project rather than a company, and the upstream from which Ubuntu and many others are derived. Version 13, codenamed trixie, was released in August 2025. What makes this image different from the standard Debian 13 image is the package profile: a named, version pinned set of 63 networking packages, every one of them from Debian's own main component, installed and ready.

That single component matters. Debian has no main/universe split and no paid support tier — main is the DFSG free archive that the Debian Security Team covers, followed by Debian LTS. Every package on this image is patched the same way, for free, by the same team, for the life of the release. There is no subscription that unlocks fixes you would otherwise be missing.

Be clear about what this is and what it is not. It is not a router, a firewall appliance, or a security product. It is the standard Debian 13 image with a documented toolbox already on it, saving you the apt install list you would otherwise type on every jump host, bastion or diagnostic VM. There is no third party software, no vendor repository, and nothing on the image that Debian does not publish.

Every daemon the profile carries is installed but disabled — nftables, OpenVPN, FRR, BIRD, lldpd, vnstat, conntrackd, netfilter-persistent and iperf3 are all present and all switched off. A freshly deployed machine listens on port 22 and nothing else. Turning a service on is a deliberate act you take, not a default you have to undo.

The image describes itself: a manifest generated from its own package database ships at /usr/share/cloudimg/debian-13-pkg-networking.manifest, naming every package, its version, its component, and what was deliberately left out and why.

What's included:

  • Debian 13 (trixie) with 63 networking packages preinstalled, every one from main on Debian's own archive
  • Capture and analysis: tcpdump, tshark, ngrep, tcpflow, ssldump
  • Reachability and paths: ping, tracepath, arping, traceroute, tcptraceroute, mtr, fping, httping, ndisc6
  • Interfaces, links and bonding: iproute2, net-tools, ethtool, bridge-utils, vlan, ifenslave, ethstatus
  • Filtering and connection tracking: nftables, iptables, ipset, ebtables, arptables, conntrack, conntrackd, iptables-persistent
  • Tunnels and routing: wireguard-tools, openvpn, frr, bird2
  • Naming and discovery: bind9-dnsutils (dig), bind9-host, ldnsutils (drill), dnstracer, whois, ldap-utils, lldpd, snmp
  • Throughput and live monitoring: iperf3, iftop, nload, bmon, nethogs, ifstat, vnstat, iptraf-ng
  • Addressing maths: ipcalc, ipcalc-ng, sipcalc, ipv6calc
  • Sockets and transfer: netcat-openbsd, socat, curl, wget, openssh-client, inetutils-telnet
  • A shipped manifest derived from the image's own package database, so the description cannot drift from what is installed
  • Every available security update applied at build time, with unattended-upgrades armed so the machine keeps patching itself
  • Gen2 Hyper V support and 24/7 cloudimg support

What's deliberately NOT included:

  • Offensive and dual use tooling. nmap, hping3, masscan, zmap, ettercap, aircrack-ng, sqlmap, hydra and their relatives are excluded by design. They are yours to install if your work needs them; they are not something a general purpose image should ship by default, and they are a recurring source of antivirus false positives on cloud marketplaces.
  • arping (the standalone package). It declares a hard, unversioned conflict with iputils-arping, so the two cannot coexist. iputils-arping won because the image already ships two other binaries from the same iputils source package. You still have the arping command — it comes from iputils-arping.
  • isc-dhcp-client. Debian's own debian-security-support list records the isc-dhcp source as non supported since 2023-07-05. Nothing on this image should depend on a package Debian has stopped patching.
  • zfsutils-linux. It lives in contrib, not main, and this profile is main only.

Platform: Microsoft Azure (Gen2 Hyper V, x64) Default user: azureuser

Security posture

This image ships with no known credential. There is no default password and no baked in SSH key:

  • The root account password is locked, so no one can log in as root with a password.
  • PermitRootLogin is set to no, so root has no SSH login path at all.
  • PasswordAuthentication is disabled, so every login is by key.
  • The only key that works is the public key you supply when you create the virtual machine. Azure injects it into azureuser at first boot, so no two machines you launch ever share a secret.
  • The machine identity and the SSH host keys are regenerated uniquely on every instance.
  • Every daemon the profile carries ships disabled and stopped. The off box listening set is exactly {22} on TCP and {68} on UDP, which is the DHCP client and nothing else.
  • LLMNR is switched off. Stock Debian 13 enables link local multicast name resolution in systemd-resolved, which binds TCP and UDP port 5355 on every interface. Nothing here needs it, so this image disables it and the port is closed.
  • dumpcap is not setuid and carries no file capabilities, so packet capture requires root rather than group membership.
  • No package on the image carries limited or ended security support in debian-security-support.

Prerequisites

Before deploying this image, ensure you have:

  1. An active Microsoft Azure subscription
  2. Access to the Azure Portal or Azure CLI
  3. An SSH key pair for Linux VM access
  4. Familiarity with Azure VM management

Recommended VM Size: Standard_B2s (2 vCPU, 4 GB RAM) or larger.

Disk size: the image ships as a 30 GiB OS disk. The profile and its dependencies add roughly 311 MB, so a stock deployment uses about 1.4 GB and leaves around 27 GB free.

Step 1: Deploy the Virtual Machine

Option A: Azure Portal

  1. Sign in to the Azure Portal
  2. Search the Marketplace for Debian 13 Networking Tools and select the cloudimg offering
  3. Click Create
  4. Choose your subscription, resource group and region
  5. Set the VM size to Standard_B2s or larger
  6. Under Administrator account, choose SSH public key, leave the username as azureuser, and paste your public key
  7. Under Inbound port rules, allow SSH (22) only, and restrict the source to your own management address range
  8. Review and create

Option B: Azure CLI

az vm create \
  --resource-group my-resource-group \
  --name debian-nettools \
  --image cloudimg:debian-13-pkg-networking:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard

Step 2: Connect via SSH

ssh azureuser@<vm-ip>

Replace <vm-ip> with your virtual machine's public IP address.

Step 3: Confirm the release and the profile

Check you have the release you expect:

grep -E '^(PRETTY_NAME|VERSION|VERSION_ID|ID)=' /etc/os-release
uname -srm
cat /etc/debian_version

Expected output:

PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
VERSION_ID="13"
VERSION="13 (trixie)"
ID=debian
Linux 6.12.107+deb13-cloud-amd64 x86_64
13.7

The terminal shows the os-release fields reporting Debian GNU/Linux 13 trixie with VERSION_ID 13, uname reporting an x86_64 cloud kernel, debian_version reporting the 13.7 point release, dpkg print-architecture reporting amd64, no held packages and zero pending upgrades

Now confirm the profile. Every entry resolves to one component, which is the whole point on Debian:

awk -F'\t' 'NF>=3{print $3}' /usr/share/cloudimg/debian-13-pkg-networking.manifest | sort | uniq -c

Expected output:

     64 main

That is the 63 networking packages plus debian-security-support, the one package added so the image can report its own support status (Step 6 uses it).

The terminal shows the manifest reporting 64 main packages and no other component, 454 packages installed in total, a sample of the toolbox each reporting its own version including iproute2, tcpdump, mtr, nftables, wireguard-tools, TShark, iperf3, conntrack, dig and socat, and df reporting 27 GB free on the root filesystem

Step 4: Read the shipped manifest

The manifest is generated from the image's own package database at build time, so it cannot drift from what is actually installed:

head -8 /usr/share/cloudimg/debian-13-pkg-networking.manifest

Expected output (the generation timestamp will differ):

# cloudimg debian-13-pkg-networking — shipped package profile
# Derived from the dpkg database at build time. Do not hand-edit.
# generated: 2026-09-18T21:26:26Z
# suite: trixie (Debian 13) — every entry is component MAIN
#
# [main] — Debian Security Team coverage, then Debian LTS to 2030-06-30
iproute2    6.15.0-1    main
net-tools   2.10-1.3    main

List the profile with the versions you actually have:

awk -F'\t' 'NF>=3 && $3=="main"{printf "%-22s %s\n",$1,$2}' /usr/share/cloudimg/debian-13-pkg-networking.manifest | head -8

Expected output:

iproute2               6.15.0-1
net-tools              2.10-1.3
tcpdump                4.99.5-2
traceroute             1:2.1.6-1
mtr-tiny               0.95-1.1+b1
iperf3                 3.18-2+deb13u2
ethtool                1:6.14.2-1
iputils-ping           3:20240905-3

Every package resolves to Debian's own archive. There is no third party repository on this image:

apt-cache policy tcpdump

Expected output:

tcpdump:
  Installed: 4.99.5-2
  Candidate: 4.99.5-2
  Version table:
 *** 4.99.5-2 500
        500 mirror+file:/etc/apt/mirrors/debian.list trixie/main amd64 Packages
        100 /var/lib/dpkg/status

The only source offering this package is trixie/main. The mirror+file: URI is Debian's own Azure mirror list, azure.deb.debian.cloud, which the official Debian cloud images use so that package downloads stay inside Azure's network. Every package on the image answers the same way.

trixie-backports is enabled in the apt sources, as it is on stock Debian cloud images, but no package on this image comes from it — backports carry priority 100 against the main archive's 500, so apt never selects them unless you ask for one explicitly.

Step 5: Confirm nothing is listening

This is the property that makes the image safe to deploy as it stands. Every service is present and switched off:

systemctl list-unit-files nftables.service frr.service lldpd.service openvpn.service vnstat.service bird.service conntrackd.service netfilter-persistent.service

Expected output:

UNIT FILE                    STATE    PRESET
bird.service                 disabled enabled
conntrackd.service           disabled enabled
frr.service                  disabled enabled
lldpd.service                disabled enabled
netfilter-persistent.service disabled enabled
nftables.service             disabled enabled
openvpn.service              disabled enabled
vnstat.service               disabled enabled

8 unit files listed.

Note the two columns. PRESET is what Debian would normally do with each unit — enable it. STATE is what this image actually ships — disabled. That gap is the deliberate choice this product makes. Those eight are the ones with a plain name; the profile also ships the templated units frr@, openvpn@, openvpn-client@, openvpn-server@ and wg-quick@, which start nothing until you name an instance.

And the listening set:

ss -tln | awk '$1=="LISTEN"{print $1, $4}' | sort -u

Expected output:

LISTEN 0.0.0.0:22
LISTEN 127.0.0.53%lo:53
LISTEN 127.0.0.54:53
LISTEN [::]:22

The only socket reachable from the network is SSH on port 22. The two entries on 127.0.0.53 and 127.0.0.54 are systemd-resolved, Debian's stock local DNS stub; they are bound to loopback and cannot be reached from outside the machine.

UDP is worth checking too, because this is where stock Debian differs:

ss -uln | awk 'NR>1{print $4}' | sort -u

Expected output:

10.0.0.10%eth0:68
127.0.0.1:323
127.0.0.53%lo:53
127.0.0.54:53
[::1]:323

Port 68 is the DHCP client, and 323 is chrony on loopback. There is no 5355. Stock Debian 13 enables LLMNR in systemd-resolved, which binds TCP and UDP 5355 on every interface; this image turns it off:

resolvectl status | grep -E 'Protocols|Current Scopes' | head -2

Expected output:

         Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
    Current Scopes: DNS

The leading - on -LLMNR is the confirmation. If you want it back, remove /etc/systemd/resolved.conf.d/20-cloudimg-no-llmnr.conf and restart systemd-resolved.

The terminal shows every TCP listener with a summary confirming only port 22 is reachable from the network, the UDP set containing 68 and loopback ports with no 5355, resolvectl reporting -LLMNR, all fifteen profile units reporting disabled, the root account reporting L for locked, and sshd reporting permitrootlogin no and passwordauthentication no with clientaliveinterval 120

Step 6: Check the patch level and the support position

The image is fully patched at build time:

apt-mark showhold
sudo apt-get update -qq
sudo apt-get -s dist-upgrade | grep -c '^Inst ' || true

apt-mark showhold prints nothing when no package is held. The count is the number of updates still pending, and will grow over time as Debian publishes new ones — unattended-upgrades applies them for you.

More importantly, nothing on this image has limited or ended security support. Debian publishes that list in the debian-security-support package, which ships on this image so you can check it yourself at any time:

sudo check-support-status --no-heading

Expected output:

Nothing. That empty result is the point: check-support-status names every installed package whose security support has ended or is limited, and on this image it names none. Compare that with Debian's own list of packages it would have flagged:

grep -vE '^#|^$' /usr/share/debian-security-support/security-support.deb13 | wc -l
grep -E '^isc-dhcp' /usr/share/debian-security-support/security-support.deb13

Expected output:

32
isc-dhcp                    non-supported   4.4.3-P1-2       2023-07-05  https://lists.isc.org/pipermail/dhcp-users/2022-October/022786.html

Thirty two packages are on Debian's watch list for trixie, and the image deliberately carries none of them — isc-dhcp-client is excluded from this profile for exactly the reason shown above.

The terminal shows check-support-status returning nothing, Debian's security-support list carrying 32 rows for trixie with the isc-dhcp non-supported entry visible, the manifest header naming trixie main, and the excluded-by-contract section naming arping, isc-dhcp-client, zfsutils-linux and the offensive tooling with the reason for each

Step 7: Use the toolbox

Everything below runs as shipped, with no service to start.

Look at your interfaces:

ip -brief address show
ip -brief link show

Expected output (your addresses will differ):

lo               UNKNOWN        127.0.0.1/8 ::1/128
eth0             UP             10.0.0.10/24 metric 100 fe80::20d:3aff:fe1c:e2c1/64

lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0             UP             00:0d:3a:1c:e2:c1 <BROADCAST,MULTICAST,UP,LOWER_UP>

Capture live traffic:

sudo timeout 20 tcpdump -i any -c 3 -n -q

Expected output (the addresses and ports will differ):

21:38:06.143187 eth0  Out IP 10.0.0.10.44276 > 168.63.129.16.80: tcp 0
21:38:06.144012 eth0  In  IP 168.63.129.16.80 > 10.0.0.10.44276: tcp 0
3 packets captured
30 packets received by filter
0 packets dropped by kernel

168.63.129.16 is Azure's own platform endpoint (the "wire server") — seeing it here is normal.

Query DNS. You have two independent resolvers on this image, dig from BIND and drill from ldns:

dig +short A www.cloudimg.co.uk | head -3
dig +noall +answer NS debian.org | head -2

Expected output:

d14bmdyrx9dte8.cloudfront.net.
3.167.88.56
3.167.88.51
debian.org.     614 IN  NS  nsp.dnsnode.net.
debian.org.     614 IN  NS  dns4.easydns.info.

Look up who owns an address:

whois -H 1.1.1.1 | grep -iE '^(netname|descr):' | head -3

Expected output:

netname:        APNIC-LABS
descr:          APNIC and Cloudflare DNS Resolver project
descr:          Routed globally by AS13335/Cloudflare

Measure throughput. iperf3 normally needs a server at the far end, but you can prove the tool works against your own loopback before you point it anywhere:

(iperf3 -s -1 -p 5399 -B 127.0.0.1 >/dev/null 2>&1 &) ; sleep 1; iperf3 -c 127.0.0.1 -p 5399 -t 1 -f m | tail -4

Expected output (the rate depends on your VM size):

[  5]   0.00-1.00   sec  2.53 GBytes  21707 Mbits/sec    0            sender
[  5]   0.00-1.00   sec  2.53 GBytes  21707 Mbits/sec                  receiver

iperf Done.

The -1 flag makes the server exit after one connection, so nothing is left listening.

Inspect the packet filter:

sudo nft list tables

Expected output:

Nothing — there are no nftables tables at all, and therefore no host firewall policy on this image. Azure Network Security Groups do that job in front of the VM. If you want a host firewall as well, write /etc/nftables.conf and enable nftables.service, or use iptables and save your rules with netfilter-persistent save.

Step 8: Turn a service on when you want it

Nothing starts by itself. When you do want a daemon, enable it explicitly:

# Example only — run these when you actually want the service.
sudo systemctl enable --now nftables.service              # load /etc/nftables.conf at boot
sudo systemctl enable --now vnstat.service                # keep long term interface counters
sudo systemctl enable --now lldpd.service                 # discover neighbours over LLDP
sudo systemctl enable --now netfilter-persistent.service  # restore saved iptables rules at boot

Three things worth knowing before you enable anything:

  • Open the port in your Network Security Group too. The image does not filter, but Azure does. A service that is running and still unreachable is almost always an NSG rule, not the VM.
  • nftables.service and netfilter-persistent.service do the same job two different ways. Enable one, not both — nftables.service loads /etc/nftables.conf, netfilter-persistent replays rules saved from iptables.
  • tshark capture as a non-root user is not available as shipped. dumpcap is deliberately left without the setuid bit and without cap_net_raw, so capture requires sudo. If you want group based capture instead, run sudo dpkg-reconfigure wireshark-common, answer yes, and add your account to the wireshark group.

Step 9: IPsec on this image

This image applies the standard cloudimg mitigation for CVE-2026-43284 and CVE-2026-43500 by preventing the kernel's ESP and IP payload compression modules from loading:

cat /etc/modprobe.d/dirtyfrag.conf

Expected output:

install esp4 /bin/false
install esp6 /bin/false
install ipcomp /bin/false
install ipcomp4 /bin/false
install ipcomp6 /bin/false
install rxrpc /bin/false

This does not affect WireGuard or OpenVPN, which are the two tunnel implementations on this image — neither uses kernel ESP. It does mean that if you install strongswan or libreswan and try to terminate an IPsec tunnel on this machine, the kernel will refuse to load the modules it needs. If that is your use case, remove the file and reboot:

# Only if you are terminating IPsec ON this VM.
sudo rm /etc/modprobe.d/dirtyfrag.conf
sudo reboot

Traffic through an Azure VPN Gateway is unaffected — the gateway terminates IPsec, not your VM.

Common Use Cases

  • Diagnostic jump host. Put one of these in a VNet and you have capture, DNS, path and throughput tools ready when something breaks, without installing packages during an incident.
  • Bastion with a toolbox. The image listens only on SSH, so it is safe to place at the edge of a subnet with an NSG in front of it.
  • Connectivity validation in CI. Drive dig, fping, httping, socat and iperf3 from a pipeline to assert a landing zone is wired the way the design says.
  • Network lab. frr and bird2 are both present for BGP and OSPF work, disabled until you configure them.
  • Golden base for a network appliance. Start from a known, documented package set rather than a bare image plus a long apt install line.

Troubleshooting

Cannot connect via SSH

Check your Network Security Group allows inbound TCP 22 from your address, that you are connecting as azureuser, and that you are offering the private key matching the public key you supplied at deployment. Password login is disabled by design, and root cannot log in at all.

traceroute and mtr show ??? for every hop

This is expected on Azure, not a fault on the image. The Azure fabric does not return ICMP time exceeded messages for intermediate hops, so hop by hop tools cannot see the path inside the platform network. tracepath behaves the same way. Use tcpdump, dig, httping and iperf3 for reachability instead, and Azure's own Network Watcher for path analysis.

A service is installed but not running

That is the design — every daemon ships disabled. systemctl enable --now <service> starts it and makes it survive a reboot. Check systemctl status <service> and journalctl -u <service> if it does not come up.

nmap is not installed

It is excluded deliberately, along with the other offensive and dual use tools. Install it yourself if your work needs it: sudo apt install nmap.

arping behaves differently from the manual page I found

There are two different arping programs in Debian. This image ships the one from iputils-arping, which sends ARP requests to an IP address; the standalone arping package, which can also ping a MAC address directly, conflicts with it and cannot be installed alongside. arping --help shows which options you actually have.

Package manager issues

sudo apt-get update
sudo apt-get -f install

If apt reports held packages, apt-mark showhold will name them; there are none on a freshly deployed image.

Important Notes

  • This is the standard Debian 13 image with a documented package profile added. It is not a router, firewall or security appliance, and cloudimg makes no such claim for it.
  • Every package comes from Debian's main component on Debian's own archive. Nothing on the image comes from contrib, non-free, trixie-backports or a third party repository.
  • Debian 13 has Debian Security Team support until 2028-08-09, followed by Debian LTS until 2030-06-30.
  • The image applies security updates automatically through unattended-upgrades, as stock Debian does.
  • No host firewall is configured. Azure Network Security Groups filter traffic in front of the VM.
  • Debian is a registered trademark of Software in the Public Interest, Inc. cloudimg is not affiliated with or endorsed by the Debian Project or SPI.

Support

cloudimg provides 24/7 support for this image. Contact support through the Azure Marketplace listing or at www.cloudimg.co.uk.