Portspoof emulates open ports and service signatures across all 65535 TCP ports, turning the reconnaissance phase from a quick scan into a long, resource-intensive process. Scanners see thousands of convincing but fake services, making it impractical to identify the real attack surface.
- Overview
- Key Features
- How It Works
- Design Approach
- Installation
- Configuration
- Usage
- Hardening with iptables
- Portspoof Pro
- Authors & License
The primary goal of Portspoof is to make reconnaissance slow, costly, and unreliable for attackers. Instead of a standard 5-second Nmap scan that maps every real service on a system, an attacker facing Portspoof sees 65535 open ports, each running what looks like a different legitimate service. There is no quick way to tell which ones are real.
- All 65535 TCP Ports Are Always Open: Instead of informing an attacker that a port is CLOSED or FILTERED, Portspoof returns
SYN+ACKfor every connection attempt. - Service Emulation: Over 9000 dynamic service signatures generated from regular expressions. Every port responds to probes with a different, convincing service identity.
- Mixed Delivery Modes: Each port gets a different behavioral profile at startup (immediate banner, delayed response, or silent hold) with hold times spread across a wide range. Full-range version detection (
nmap -sV -p-) goes well beyond practical limits. - Offensive Defense: Can be used as an 'Exploitation Framework Frontend' to exploit vulnerabilities in the attacker's own scanning tools.
- Lightweight & Secure: Runs in userland (no root privileges required), binds to just ONE TCP port per running instance, and has marginal CPU/memory usage.
Example Nmap Scan:
$ nmap -p 1-20 target
Starting Nmap 7.80 ( https://nmap.org )
Nmap scan report for target
Host is up (0.00016s latency).
PORT STATE SERVICE
1/tcp open tcpmux
2/tcp open compressnet
3/tcp open compressnet
4/tcp open unknown
5/tcp open rje
6/tcp open unknown
7/tcp open echo
8/tcp open unknown
9/tcp open discard
10/tcp open unknown
11/tcp open systat
12/tcp open unknown
13/tcp open daytime
14/tcp open unknown
15/tcp open netstat
16/tcp open unknown
17/tcp open qotd
18/tcp open unknown
19/tcp open chargen
20/tcp open ftp-dataPortspoof responds to service probes with valid, dynamically generated signatures based on a massive regular expression database. As a result, an attacker will not be able to determine which port numbers your system is truly using.
Example Version Scan (ports 1–100):
$ nmap -sV -p 1-100 target
Nmap scan report for target
Host is up (0.00016s latency).
PORT STATE SERVICE VERSION
1/tcp open tcpmux?
2/tcp open irc ircu ircd
3/tcp open tcpwrapped
5/tcp open http Polycom CMA Global Address Book (GAB) httpd
10/tcp open http PGP Universal httpd
11/tcp open http SnapStream Media Beyond TV PVR http config
12/tcp open pop3 Novell GroupWise pop3d
13/tcp open http micro_httpd
15/tcp open ssh OpenSSH r (protocol 8; NCSA GSSAPI authentication patch)
16/tcp open ftp QMS/Minolta Magicolor 2200 DeskLaser printer ftpd
17/tcp open smtp Network Box smtpd
21/tcp open ftp?
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
23/tcp open tcpwrapped
25/tcp open smtp?
27/tcp open http BMC/Marimba Management http config
37/tcp open http Indy httpd qlRKjiF
39/tcp open pop3
41/tcp open ftp VSE ftpd WhH
43/tcp open imap Scalix imapd 6
46/tcp open telnet AXIS webcam telnetd 96747 (Linux)
49/tcp open smtp Openwave Email Mx smtpd
50/tcp open http 3Ware web interface 3v (RAID storage)
51/tcp open ftp WebStar 4dftp ...
53/tcp open tcpwrapped
55/tcp open webdav Tonido WebDAV
56/tcp open tor-control Tor control port (Authentication required)
59/tcp open irc ircu ircd
60/tcp open rtsp GStreamer rtspd
64/tcp open http BaseHTTPServer CAxoE (Mercurial hg serve; Python LDkW)
66/tcp open telnet Slirp PPP/SLIP-on-terminal emulator telnetd
70/tcp open smtp qpsmtpd
71/tcp open smtp Microsoft Exchange smtpd
73/tcp open http Avaya IP Office VoIP PBX httpd
77/tcp open smtp Zeus SMTPS smtpd
79/tcp open ftp Sambar ftpd
80/tcp open tcpwrapped
81/tcp open imap-proxy nginx imap proxy
82/tcp open ssh (protocol 811)
83/tcp open http peercast.org
88/tcp open csta Alcatel OmniPCX Enterprise
90/tcp open http WASD httpd
91/tcp open http Fortinet FortiGate 50B firewall http config
93/tcp open imap ModusMail imapd 4
98/tcp open ssh Sysax Multi Server sshd 7 (protocol 940)
99/tcp open http 2Wire HomePortal http config 5473
100/tcp open newacct?Combined, these techniques mean:
- There is no fast way to distinguish real services from fake ones. Timing, behavior, and banner content all vary across the port range.
- A full version scan (
nmap -sV -p-) with default tarpit settings takes 10+ hours and generates hundreds of megabytes of bogus data. - The attacker's scanner burns time and threads on connections that lead nowhere.
Real services (SSH, SMTP, FTP, HTTP) send a banner and keep the connection open, waiting for client input. Convincing emulation means doing the same: accept, send, hold. But a thread-per-client model burns memory and CPU on context switching, and at scale the defender runs out of resources before the attacker runs out of patience. The deception tool becomes a self-DOS vector.
The approach: a single-threaded epoll event loop. Each port is assigned a delivery mode at startup: some push a banner immediately, some wait for the client to send data before responding, and some stay silent. Hold times are spread across orders of magnitude (tens of milliseconds to minutes) with per-connection jitter, so repeated probes to the same port don't return identical timing.
This matters because without it, an attacker can send garbage to every port and measure response timing: real services close fast (wrong protocol), while a naive tarpit holds for seconds. With mixed modes and a wide timing spread, thousands of fake ports also close in the same range as real services. There's no clean threshold to filter on.
The economics work because of asymmetry:
- Defender cost: ~1–2 KB kernel memory per idle connection. The epoll loop is single-threaded, no context switching overhead. A modest box holds 10k+ concurrent connections without breaking a sweat.
- Attacker cost: time and effort. A port scan tells them nothing — every port is open. To find real services they need version detection across all 65535 ports, then protocol-level probing on anything that looks plausible. A 5-second scan becomes 10+ hours of active work, the result is still a haystack, and most attackers move on to an easier target.
Per-port delivery modes are fixed for the lifetime of the process but unpredictable across restarts. Hold times have a per-connection random component so repeated probes show natural variance, similar to real services under load.
v2.0 replaces the original banner-and-close behavior that was vulnerable to a connection-closure bypass (see Vicarius/Hored1971 blog post). The tarpit engine holds all connections open with mixed timing, defeating connection-closure filtering, timing fingerprinting, banner analysis, and statistical pattern modeling.
Ensure you have a C++ compiler and CMake (3.10+) installed.
mkdir build && cd build
cmake -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
make
sudo make installPortspoof runs in userland but relies on system firewall rules to intercept traffic destined for other ports.
Redirect all incoming TCP traffic (ports 1-65535) to the Portspoof port (default 4444).
Linux (iptables):
# Exclude real services first, then redirect the rest to Portspoof
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22 -j RETURN
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -j REDIRECT --to-ports 4444Note: Replace eth0 with your network interface. Add a RETURN rule for each port running a real service.
To make this persistent, you can save your iptables rules or use the iptables-config provided in the system_files directory.
You can add Portspoof to your startup scripts using the examples in system_files/init.d/.
This mode generates and feeds port scanners with bogus service signatures.
portspoof -c /etc/portspoof.conf -s /etc/portspoof_signatures -DWith custom tarpit timings (hold each connection between 10 and 60 seconds):
portspoof -s /etc/portspoof_signatures -t 10 -T 60 -DThis mode simply returns an OPEN state for every connection attempt without sending service banners. Connections are still tarpitted.
portspoof -DPortspoof can be used to fuzz scanning tools by sending random or wordlist-based payloads.
Fuzz with internal generator:
# Generates random payloads of random size
portspoof -1 -vFuzz with a wordlist:
portspoof -f payloads.txt -vThe basic REDIRECT rule above works, but an aggressive scanner can still try to overwhelm Portspoof with connections. The following ruleset adds rate limiting and automatic banning for hosts that exceed the connection threshold. Ports hosting real services (SSH in this example) are excluded from the redirect but still protected by the global ban rule.
# --- NAT: redirect everything except real services ---
# add a RETURN rule for each port you actually use (SSH, HTTP, etc.)
iptables -t nat -A PREROUTING -p tcp --dport 22 -j RETURN
iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 4444
# --- FILTER: defense in depth ---
# allow loopback (critical: prevents breaking local services)
iptables -A INPUT -i lo -j ACCEPT
# if this IP was flagged as abusive, drop everything (silent, no RST)
iptables -A INPUT -m recent --name PORTSCAN --rcheck --seconds 60 -j DROP
# rate-limit new SYNs per source IP
iptables -A INPUT -p tcp --syn -m hashlimit \
--hashlimit-above 10/sec --hashlimit-burst 30 \
--hashlimit-mode srcip --hashlimit-name syn_throttle -j DROP
# if a single IP holds 100+ connections to portspoof, flag and drop
iptables -A INPUT -p tcp --syn --dport 4444 -m connlimit \
--connlimit-above 100 --connlimit-mask 32 \
-m recent --name PORTSCAN --set -j DROP
# allow established traffic and new connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --syn -j ACCEPT
iptables -A INPUT -j DROPFor high-traffic deployments, increase the xt_recent list size:
echo "options xt_recent ip_list_tot=10000" > /etc/modprobe.d/xt_recent.confAnd tune kernel connection tracking:
sysctl -w net.netfilter.nf_conntrack_max=131072
sysctl -w net.core.somaxconn=4096Portspoof Pro scales deception from a single host to an entire network. A single sensor emulates full /16 networks: thousands of IPs, each with unique services across all ports, holding stateful multi-step conversations.
- Network-wide deception. Turn dark IP space and unused subnets into an active deception grid. Every emulated host presents unique services with a different personality per source IP. Active tarpitting exhausts attacker socket pools and throttles automated tools.
- Scan detection and tool fingerprinting. Detects SYN, FIN, NULL, XMAS, ACK scan techniques. Fingerprints Nmap, Masscan, ZMap, and custom scanners. Structured JSON telemetry with MITRE ATT&CK mapping, streamed to your SIEM.
- Production-safe deployment. Runs in a sandboxed environment alongside production traffic. Routing policies steer deception traffic to the sensor. No inline taps, no risk to real workloads.
- Compliance out of the box. Supports NIS2, DORA, ISO 27001, NIST CSF, and CIS Controls.
Author: Piotr Duszyński (@drk1wi)
License: GNU General Public License v2.0 (GPLv2). See the LICENSE file for details.
For commercial, legitimate applications, please contact the author for the appropriate licensing arrangements.
If you encounter any bugs or have feature requests, please report them on the GitHub Issue Tracker or contact the author via email at piotr [at] duszynski.eu.