A small red-team toolkit for testing your own public systems
A cup containing Nmap, DNS tools, OpenSSL, testssl.sh, Swaks, WPScan, WP-CLI and ZAP—enough to check your own public IP, on-premises mail server and WordPress site without turning the assessment into the incident.
Scope
For owners and administrators checking internet-facing systems they control: one public IP, one on-premises mail domain and one WordPress site. The workflow begins with passive or bounded observations and deliberately excludes password attacks, denial-of-service testing, exploit modules and unreviewed scanning templates.
What “red-team toolkit” means here
There is no single respectable button labelled redcup that drinks the tea, tests the estate and writes a defensible report. Here the phrase means a small red-team-style toolkit used defensively: observe the outside surface, identify what is really running, check a few important controls, repair confirmed faults and repeat the same test.
The objective is not to obtain the longest possible scanner report. It is to answer three ordinary questions rather well:
- What does my public address expose from a genuinely external network?
- Does my on-premises mail service offer the ports, TLS and anti-abuse behaviour I intended?
- Is my WordPress site presenting outdated components, altered files or avoidable web weaknesses?
Run every external check from a separate connection or controlled remote host. Record the source address, target, date, expected services and stop condition before beginning. If the address belongs to a CDN, shared host, ISP or CGNAT pool, you do not own the target merely because your browser eventually reaches your site. Obtain the provider’s permission and follow its acceptable-use policy.
The kit
Eight tools, each with one proper job
These tools overlap just enough to challenge one another. External WPScan identification can be checked against the local WP-CLI inventory. Nmap’s port observation can be checked against the firewall, NAT rules and local listening processes. A certificate seen by OpenSSL can be compared with the hostname that the service was meant to present. Independent evidence is less glamorous than a red terminal, but considerably more useful on Monday morning.
Preparation
Install a clean, boring assessment station
A current Linux VM is convenient. macOS or Windows with WSL and Docker also works. Install software from its official project or your maintained operating-system repository, update it before the assessment, and record the versions. Container images should be pinned to an approved version or digest in repeatable business work.
# Debian or Ubuntu assessment workstation
sudo apt update
sudo apt install -y nmap dnsutils openssl curl swaks docker.io
# Record the tools used in the evidence folder
mkdir -p assessment-2026-08-18
nmap --version > assessment-2026-08-18/tool-versions.txt
openssl version >> assessment-2026-08-18/tool-versions.txt
swaks --version >> assessment-2026-08-18/tool-versions.txt
docker --version >> assessment-2026-08-18/tool-versions.txt
# Pull the specialist scanners from their official projects
docker pull ghcr.io/testssl/testssl.sh:latest
docker pull wpscanteam/wpscan:latest
docker pull ghcr.io/zaproxy/zaproxy:stable
WPScan uses a custom licence and may require a paid licence for commercial use. Read its current licence before using it for client or employer work. Its vulnerability data also requires an API token; the scanner still operates without one, but it cannot give you the same current vulnerability detail.
Example 01
Check your own public IP from outside
Confirm the router WAN address and compare it with an independent “what is my IP” result. Private ranges and 100.64.0.0/10 indicate NAT or CGNAT; scanning the shared public address may test the provider rather than your router. Dynamic addresses should be confirmed again immediately before the scan.
The example address 203.0.113.25 is reserved for documentation. Replace it only with your confirmed address, then run this from a phone hotspot, a second site or a small remote machine you control:
# A bounded first pass over the 1,000 most common TCP ports
nmap -Pn -sT --top-ports 1000 --reason \
-oA assessment-2026-08-18/public-ip-baseline 203.0.113.25
# Follow up only on ports that were actually open
nmap -Pn -sT -sV --version-light -p 25,443,587 \
--reason -oA assessment-2026-08-18/public-ip-services 203.0.113.25
open means a listener answered. closed means the host replied but nothing listened there. filtered means Nmap could not decide because a firewall or another obstacle prevented a conclusive reply. None of those words means “patched”. A service name in the first scan is commonly inferred from the port number; version detection provides a stronger lead, but banners can be hidden, proxied or misleading.
PORT STATE SERVICE REASON
25/tcp open smtp syn-ack
443/tcp open https syn-ack
587/tcp open submission syn-ack
3389/tcp filtered ms-wbt-server no-response
For an on-premises mail gateway, ports 25 and perhaps 443 or 587 may be expected. Public RDP, SMB, databases, hypervisor consoles, router administration or a forgotten development server require immediate ownership and justification. Check the local truth before declaring a breach:
# Linux listening processes
sudo ss -lntup
# Docker host bindings
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}'
# Windows PowerShell listening processes
Get-NetTCPConnection -State Listen | Sort-Object LocalPort
Get-Process -Id PID | Select-Object Id,ProcessName,Path,StartTime
If the port has no owner, or the listener is an unknown process accompanied by new accounts, unexpected outbound connections or disabled security controls, preserve the Nmap output and local evidence, restrict the exposure safely and follow the web-server compromise playbook or Linux compromise guide. Do not start with a reboot; it may remove the volatile evidence and leave the attacker’s stolen credentials entirely refreshed.
Example 02
Check an on-premises mail server without mailing the entire office
Use example.com and mail.example.com as placeholders. Begin with DNS because the best-configured SMTP daemon cannot repair an MX record pointing at last year’s appliance.
# Routing and sender-authentication policy
dig +short MX example.com
dig +short TXT example.com
dig +short TXT _dmarc.example.com
# Use the selector from your mail configuration or a DKIM-Signature header
dig +short TXT selector1._domainkey.example.com
# Transport policy and TLS failure reporting
dig +short TXT _mta-sts.example.com
curl -fsS https://mta-sts.example.com/.well-known/mta-sts.txt
dig +short TXT _smtp._tls.example.com
Expected evidence is specific: MX hosts you recognise; one valid SPF record rather than several competing ones; a DMARC record with an intentional policy and monitored reporting address; a DKIM key for the selector actually used; and, where deployed, matching MTA-STS and TLS reporting records. Do not copy a strict DMARC or MTA-STS policy from an article and deploy it before monitoring legitimate senders and backup MX paths. Email punishes optimism by delaying someone else’s invoice.
Next, check the public ports and the SMTP STARTTLS certificate:
# Scan only the mail ports you intend to expose
nmap -Pn -sT -sV --version-light \
-p 25,465,587,993 --reason \
-oA assessment-2026-08-18/mail-ports mail.example.com
# SMTP on port 25 upgrades to TLS with STARTTLS
openssl s_client -starttls smtp \
-connect mail.example.com:25 \
-servername mail.example.com \
-verify_return_error -brief
# Port 465 normally begins with implicit TLS
openssl s_client -connect mail.example.com:465 \
-servername mail.example.com \
-verify_return_error -brief
A useful result shows a successful handshake, a certificate valid for the intended hostname, a trusted chain and a modern protocol. If -verify_return_error aborts, inspect the exact chain or hostname error rather than adding an option to ignore it. For a broader protocol and cipher review, use testssl.sh against the precise owned service:
docker run --rm -t ghcr.io/testssl/testssl.sh:latest \
--starttls smtp --warnings batch \
mail.example.com:25
docker run --rm -t ghcr.io/testssl/testssl.sh:latest \
--warnings batch mail.example.com:465
Finally, ask whether the gateway behaves like a relay. Swaks can stop after the recipient command, before sending message data. Use two domains and recipients that you control, and perform the test from outside without authentication:
# Expected result: a 550/553/554-style relay denial at or after RCPT TO
# The command stops before DATA, so no message body is submitted.
swaks --server mail.example.com --port 25 \
--from relay-test@sender.example \
--to relay-test@recipient.example \
--quit-after RCPT
The exact SMTP code varies, but an unauthenticated external client should not be permitted to relay from one unrelated external domain to another. Do not confuse acceptance of mail for your own local domain with open relay behaviour. If relay is allowed unexpectedly, restrict relay permissions immediately, review connector and receive rules, search logs for abuse, rotate exposed credentials and check whether the public IP is listed by reputation services. Then repeat the same RCPT-only test.
Unauthenticated relay succeeds
Restrict relay to authenticated users and approved internal sources, investigate logs and queues, then repeat the controlled test.
STARTTLS absent or certificate invalid
Correct the connector, certificate chain, hostname and renewal path. Test every advertised MX, not only the favourite one.
SPF, DKIM or DMARC incomplete
Inventory legitimate senders, deploy in monitored stages, and make reporting go somewhere a human or system actually reads.
Legacy POP/IMAP or admin ports public
Remove them where unused; otherwise require modern TLS, strong authentication, patching, logging and a written business reason.
Example 03
Check a WordPress site from both sides
External checks show what a visitor can observe. Local checks show the installed components and file integrity. Use both. Before touching production, confirm a restorable backup, a maintenance window, application monitoring and a contact who can stop the test. Start with headers and TLS:
# Save the response headers without downloading the page body
curl -sS -D assessment-2026-08-18/wordpress-headers.txt \
-o /dev/null https://www.example.com/
# Review the TLS service separately
docker run --rm -t ghcr.io/testssl/testssl.sh:latest \
--warnings batch www.example.com:443
Look for a valid redirect from HTTP to HTTPS, the expected certificate, sensible cookie flags and suitable security headers. Header scanners provide leads, not universal policy: Content Security Policy in particular must match the application and should be staged carefully. The related TLS and security headers guide explains how to deploy and verify them without conducting configuration by folklore.
Run WPScan in passive plugin and theme detection mode. The example enumerates only components with known vulnerability data; it does not enumerate usernames or attempt passwords:
# Set the token in your shell; do not paste it into screenshots or reports.
export WPSCAN_API_TOKEN='YOUR_WPSCAN_API_TOKEN'
# Save output on the host and retain the scanner database between runs.
docker run --rm \
-e WPSCAN_API_TOKEN \
-v wpscan-db:/wpscan/.cache/wpscan/db \
--mount type=bind,source="$PWD/assessment-2026-08-18",target=/output \
wpscanteam/wpscan:latest \
--url https://www.example.com/ \
--enumerate vp,vt \
--plugins-detection passive \
--output /output/wpscan-passive.txt
WPScan may identify versions from public assets, metadata or known paths. A finding becomes actionable only after you confirm that component locally, determine whether the deployed version and configuration meet the vendor advisory’s affected conditions, and establish that the relevant feature is reachable. Do not add --passwords, username enumeration, aggressive detection or exploit code merely because the programme supports them.
On the WordPress host, run WP-CLI as the site owner or another appropriate low-privilege account:
# Installed versions and available updates
wp core version
wp plugin list --fields=name,status,version,update,update_version
wp theme list --fields=name,status,version,update,update_version
# Compare official WordPress files with WordPress.org checksums
wp core verify-checksums --include-root --version=$(wp core version)
wp plugin verify-checksums --all --strict
A failed core checksum deserves investigation. A plugin checksum warning is not automatically malware: commercial, premium and custom plugins may have no WordPress.org checksum. Compare them with a trusted release artefact or source repository. Conversely, a successful core checksum does not inspect uploads, custom code, the database, scheduled tasks, web-server configuration or stolen administrator sessions.
Finish with ZAP Baseline. It spiders briefly and performs passive scanning rather than active attacks, but it still makes requests: keep the target and maintenance window explicit.
docker run --rm \
-v "$PWD/assessment-2026-08-18:/zap/wrk/:rw" \
-t ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t https://www.example.com \
-m 1 -r zap-wordpress.html -J zap-wordpress.json
By default, ZAP reports alerts as warnings. Review each example URL and response. Missing headers, insecure cookies, debug output or mixed content may be genuine; some alerts will be context-dependent or false positives. Repair confirmed issues in staging, deploy with rollback, then run the identical baseline again and compare reports.
Working sequence
From observation to a defensible finding
Unexpected port on the public IP
8443/tcp open from the external scanner.
Identify the NAT rule, local listener, process, package, owner and purpose. Check the same address from a second approved source if filtering varies.
If unneeded, remove the forwarding rule and listener. If unexplained or suspicious, preserve evidence and enter incident response. Repeat the original scan until the port is closed or deliberately filtered.
Mail certificate does not match the MX hostname
-verify_return_error reports a hostname or chain failure.
Check every MX host, the certificate subject alternative names, intermediate chain, expiry and service binding.
Install the correct certificate and chain, fix automatic renewal and binding, then rerun OpenSSL and testssl.sh against each MX endpoint.
WPScan reports a vulnerable plugin
WPScan associates a public plugin version with an advisory.
Confirm the installed version with WP-CLI, read the primary vendor advisory, determine the fixed version and check whether the affected feature is enabled and reachable.
Back up, test the supported update in staging, deploy it, remove abandoned components and repeat both external and local checks. If compromise indicators exist, update alone is not incident recovery.
Triage
A scanner finding is a lead; a vulnerability needs evidence
Never paste a banner into a CVE search and call the server vulnerable. Linux distributions backport fixes, appliances hide build details, reverse proxies answer on behalf of applications, and scanners occasionally possess the confidence of a man who has mistaken the coat cupboard for the railway platform.
Report
Write the evidence before the adjectives
Finding: Unexpected public administration service
Target: 203.0.113.25:8443
Observed from: authorised scanner IP, 18 Aug 2026 14:20 EEST
Evidence: Nmap XML + router NAT rule + local process/package
Expected state: no public administration interface
Risk: remote authentication surface exposed to the internet
Owner: Infrastructure
Immediate action: restricted at firewall; logs preserved
Permanent action: remove port forward; require managed VPN
Retest: identical Nmap command shows filtered from two sources
Residual risk: VPN and identity controls reviewed separately
Keep raw output, commands, versions, timestamps and screenshots that add information. Remove API tokens, credentials, internal addresses and personal data before sharing. A redacted report is still useful; a leaked scanner token is simply a very short sequel.
Validate before closing
- Every externally open port has an owner, purpose, patch path, authentication control and logging.
- Every mail MX presents the intended certificate, supports the intended TLS path and refuses unauthorised external relay.
- SPF, DKIM, DMARC and any MTA-STS/TLS reporting configuration match the real mail flow.
- WordPress core, plugins and themes are inventoried, supported and updated; checksum anomalies are explained.
- Confirmed web findings are repaired and the same ZAP, WPScan, TLS and header checks have been repeated.
- Unexpected services or compromise indicators have moved into incident response rather than disappearing into a patch ticket.
The test is complete when the before-and-after evidence supports the intended control, not when the terminal returns to the prompt.
Common mistakes
- Scanning a shared ISP, CDN or hosting address that is not actually yours.
- Running an internal scan and describing it as the internet perimeter.
- Using every NSE, Nuclei, Nikto or Metasploit module without reviewing whether it is intrusive.
- Testing mail with a real mailing list, production credentials in shell history, or a relay message that is actually delivered.
- Treating an open port, banner or automated warning as confirmed exploitation.
- Updating WordPress immediately after suspicious checksum results and overwriting evidence of compromise.
Begin narrow, save evidence and expand only when the next question requires it. Thoroughness is not measured in packets per second.
Questions people ask before pressing Enter
Does an open port mean the server is vulnerable?
No. It proves that a listener answered from the tested vantage point. Identify the real product and installed build, confirm the reachable feature, and compare it with the vendor advisory before calling it vulnerable.
Can I run these checks against a production WordPress site?
Begin with the passive and bounded checks in a maintenance window, confirm backups and monitoring, and obtain permission from the owner and hosting provider. Do not add password attacks, exploit modules, denial-of-service checks or unreviewed templates.
Is a scanner report a penetration test?
No. A scanner provides observations and leads. A defensible assessment also needs scope, architecture, manual validation, business context, remediation and a repeat test.
Should I add Greenbone, Nessus or another vulnerability scanner?
They can add breadth, especially with authenticated scanning, but only after asset ownership, credentials, maintenance windows, exclusions and remediation ownership are established. A larger scanner does not repair a smaller process.
Safety boundary
Use these commands only on systems and addresses you own or are explicitly authorised to assess. Check the rules of your ISP, cloud provider and hosting company. Start with passive or bounded checks, avoid brute force and exploitation on production, preserve evidence, and stop if availability or scope changes.
Primary references
- Nmap Reference GuideNmap Project
- openssl s_client documentationOpenSSL Project
- testssl.sh documentation and releasestestssl.sh project
- Swaks — Swiss Army Knife for SMTPSwaks project
- WPScan User DocumentationWPScan Team
- WP-CLI core checksum verificationWordPress.org
- Hardening WordPressWordPress.org
- ZAP Baseline ScanOWASP ZAP
- RFC 8461: SMTP MTA Strict Transport SecurityRFC Editor
- RFC 8460: SMTP TLS ReportingRFC Editor
Editorial status: first edition. Tool behaviour, licences and command options change; verify them against the linked primary documentation before an assessment.