Network Log Forensics
- Network Log Forensics
Network logs are the written record of who spoke to whom, when, on which port, and with what outcome. Unlike a packet capture, logs are always-on, compact, and frequently retained for weeks or months — making them the most common source of network evidence in enterprise investigations. This page covers how to read, query, and correlate the major log types encountered in enterprise environments.
For packet-level acquisition and analysis, see Network Forensics.
Foundations: Time, Attribution, and Evidentiary Limits
Before analyzing any log, establish these constraints. Skipping them is the most common source of attribution errors.
Timestamps and Timezone
Log timestamps mean nothing without a timezone. Enterprise logs are frequently a mix of UTC, local time, and offset-from-UTC. A three-hour discrepancy between a firewall log in UTC and a Windows event log in US/Eastern (UTC-5) during winter will appear as a two-hour gap in a timeline.
Rules:
- Convert everything to UTC before correlating across systems.
- Record what timezone each log source uses; treat it as evidence.
- Clock drift of ±30 seconds is common on unmanaged devices; ±5 minutes is possible. Note the NTP status of each source.
- Virtualization, sleep/hibernate, and live migration can cause sudden clock jumps.
IP Attribution and NAT
An IP address in a log is not an identity. In a network with NAT:
- An external source IP identifies a router, not a host. The firewall’s NAT translation log is required to identify the internal host behind a public IP.
- An internal destination IP may be a load balancer or reverse proxy. The server’s own logs are required to find the actual backend host.
- DHCP churn: a host may hold an IP for only a few hours. If you pivot on IP without constraining to a time window, you will identify the wrong device.
- MAC address randomization (enabled by default on most modern mobile OSes) defeats MAC-based attribution across time unless the device has a fixed identity.
Log Retention and Gaps
Logs that do not exist cannot be used as evidence. Before concluding “there was no connection,” confirm:
- What the retention period is for each source (firewall, DNS resolver, DHCP).
- Whether log rotation discarded relevant data before the investigation started.
- Whether a gap in time within a log represents genuine absence of activity or log rotation without a gap-free handoff.
Evidentiary Integrity
Logs on a live server are not forensically pristine. For investigation purposes:
- Hash and timestamp log files as soon as possible after acquisition.
- Prefer centralized syslog or SIEM exports over logs pulled from endpoint files, as centralized logs are harder for an attacker to tamper with retroactively.
- Note that an attacker with root access to a logging host can alter local logs. Centralized log integrity (append-only storage, write-once SIEM) is a prerequisite for logs to be admissible.
Correlation Primer
The power of network logs comes from pivoting across sources using shared observables. The three most common pivots are:
| Pivot | From → To |
|---|---|
| IP + time | Firewall deny → DHCP lease → user identity |
| Hostname | DNS query → proxy log → destination IP |
| Session | DHCP lease → VPN auth → AD login |
General investigation workflow:
- Start with a known indicator (IP, hostname, username, time of incident).
- Expand through DHCP to get MAC and time window.
- Expand through DNS to get hostnames contacted.
- Expand through firewall/proxy to get destinations and volumes.
- Enrich with Suricata/IDS alerts and NetFlow for behavioral patterns.
- Reconstruct a timeline ordered by UTC timestamp.
A worked end-to-end scenario using all of these sources is at the bottom of this page.
DHCP Logs
DHCP logs are the bridge between an IP address (seen in all other logs) and a physical or virtual machine identity (MAC address, hostname). They are almost always the first log consulted when attributing an IP to a device.
ISC dhcpd (Linux)
Default log path: /var/log/syslog or /var/log/dhcpd.log
May 12 09:14:22 dhcpd[1234]: DHCPREQUEST for 192.168.8.215 from b8:27:eb:aa:11:22 (rpi-device) via eth0
May 12 09:14:22 dhcpd[1234]: DHCPACK on 192.168.8.215 to b8:27:eb:aa:11:22 (rpi-device) via eth0
May 12 09:14:22 dhcpd[1234]: uid lease 192.168.8.215 for client b8:27:eb:aa:11:22 is assigned with a lease time of 86400 seconds
May 13 09:14:22 dhcpd[1234]: DHCPEXPIRE 192.168.8.215 to b8:27:eb:aa:11:22
Key fields:
| Field | Forensic value |
|---|---|
| Timestamp | When the IP was assigned |
DHCPACK |
Confirmed assignment (more reliable than DISCOVER/OFFER) |
DHCPEXPIRE |
When the lease ended — defines the attribution window |
| MAC address | Device identity (may be randomized on mobile) |
| Hostname | Client-supplied, not authenticated; treat as advisory |
| Lease time | Calculate when the same IP could be reassigned |
Querying the lease for a given IP:
grep 'DHCPACK on 192.168.8.215' /var/log/syslog | awk '{print $1,$2,$3,$8,$10,$11}'
Windows DHCP Server
Windows DHCP logs live in C:\Windows\System32\dhcp\ as DhcpSrvLog-Mon.log etc. Format is CSV-like:
ID,Date,Time,Description,IP Address,Host Name,MAC Address
10,05/12/25,09:14:22,Assign,192.168.8.215,LAPTOP-7XQ,b8-27-eb-aa-11-22
12,05/13/25,09:14:22,Release,192.168.8.215,LAPTOP-7XQ,b8-27-eb-aa-11-22
Event ID 10 = new lease; 11 = renew; 12 = release; 15 = deny.
Forensic pitfalls:
- Client-supplied hostnames are not authenticated; a compromised host can submit any name.
- MAC randomization (iOS, Android, Windows 11 by default) means the MAC may not persist across sessions.
- DHCP logs alone do not identify a user — they identify a device. User attribution requires a further pivot to VPN, 802.1X, or AD login logs.
DNS Logs
DNS logs show every name resolution attempted from within the network. They reveal:
- What external hosts devices contacted (by name, not just IP).
- Potential data exfiltration via DNS tunneling.
- Command-and-control domains being queried.
- Reconnaissance activity (mass reverse lookups, zone transfer attempts).
BIND Query Log
Enable in /etc/named.conf:
logging {
channel query_log {
file "/var/log/named/query.log" versions 5 size 50m;
severity dynamic;
print-time yes;
print-category yes;
};
category queries { query_log; };
};
Sample output:
12-May-2025 09:15:01.234 client 192.168.8.215#54321 (example.com): query: example.com IN A + (192.168.8.1)
12-May-2025 09:15:02.110 client 192.168.8.215#54322 (c2server.bad.example): query: c2server.bad.example IN A + (192.168.8.1)
12-May-2025 09:15:03.001 client 192.168.8.215#54323 (aGVsbG8gd29ybGQ.tunnel.attacker.io): query: aGVsbG8gd29ybGQ.tunnel.attacker.io IN TXT + (192.168.8.1)
Key fields:
| Field | Meaning |
|---|---|
| Timestamp | Query time |
| Client IP | Querying host |
| Query name | Hostname being resolved |
| Query type | A, AAAA, MX, TXT, PTR — type matters for detecting tunneling |
| Resolver IP | Which upstream resolver was used |
Windows DNS Debug Log
Enable in DNS Manager → Server Properties → Debug Logging. Log writes to %systemroot%\System32\dns\dns.log.
5/12/2025 9:15:01 AM 0D40 PACKET Snd UDP 192.168.8.215 R Q [8081 D NOERROR] A (7)example(3)com(0)
DNS tunneling indicators:
| Indicator | Description |
|---|---|
| Unusually long subdomains (>50 chars) | Data encoded in labels |
| High query rate to a single domain | Polling a C2 or exfiltrating |
| TXT queries from non-mail hosts | TXT is the preferred tunnel response type |
| High entropy in subdomain labels | Base64/hex-encoded content |
| PTR queries in non-standard ranges | Reconnaissance |
Finding long query names (DNS tunneling triage):
awk '{print length($8), $8}' /var/log/named/query.log | sort -rn | head -20
Counting queries per source to detect polling:
grep 'query:' /var/log/named/query.log | awk '{print $4}' | cut -d# -f1 | sort | uniq -c | sort -rn | head -20
Evidentiary limits: Long subdomains and TXT queries have legitimate uses (SPF, DKIM, ACME challenges, split-horizon DNS). Correlation with NetFlow volume and timing is required before concluding tunneling is present.
Firewall and NAT Logs
Firewall logs record connection attempts — allowed and denied — at the network boundary. NAT translation logs are essential for mapping a public IP seen in an external log back to the internal host that originated the traffic.
iptables / nftables (Linux)
iptables logging is configured per rule:
iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
Syslog output:
May 12 09:20:01 gw kernel: IPTABLES-DROP: IN=eth0 OUT= MAC=00:11:22:33:44:55:66:77:88:99:aa:bb:08:00
SRC=203.0.113.42 DST=192.168.8.215 LEN=44 TOS=0x00 TTL=51 ID=54321 PROTO=TCP SPT=44567 DPT=22 WINDOW=65535 SYN
Key fields:
| Field | Meaning |
|---|---|
| IN/OUT | Interface direction |
| SRC/DST | Source and destination IP |
| SPT/DPT | Source and destination port |
| PROTO | Protocol (TCP, UDP, ICMP) |
| SYN/ACK/RST | TCP flags |
| Prefix | Rule chain context (e.g., DROP, ACCEPT) |
nftables uses the same syslog format when log is used in rules.
Palo Alto Traffic Log
Palo Alto logs are CSV/syslog. Key fields in a traffic log entry:
FUTURE_USE,RECEIVE_TIME,SERIAL,TYPE,THREAT_CONTENT_TYPE,FUTURE_USE,
GENERATED_TIME,SRC_IP,DST_IP,NAT_SRC_IP,NAT_DST_IP,RULENAME,
SRC_USER,DST_USER,APPLICATION,VSYS,SRC_ZONE,DST_ZONE,INBOUND_IF,OUTBOUND_IF,
LOG_FWDING,FUTURE_USE,SESSION_ID,REPEAT_COUNT,SRC_PORT,DST_PORT,
NAT_SRC_PORT,NAT_DST_PORT,FLAGS,PROTOCOL,ACTION,BYTES,...,ELAPSED_TIME,...
The ACTION field is allow, deny, drop, reset-client, or reset-server. The APPLICATION field reflects Palo Alto’s App-ID classification, not just port numbers.
Identifying denied outbound connections (lateral movement attempt, C2 blocked):
grep ',deny,' palo_traffic.csv | awk -F',' '{print $8,$9,$25,$26,$31}' | sort | uniq -c | sort -rn
NAT Translation Logs
When traffic traverses a NAT device, the public IP visible in external logs corresponds to the NAT device, not the internal host. The NAT log records the translation:
May 12 09:21:00 fw1 kernel: NAT: src=192.168.8.215:54321 -> 203.0.113.1:61234 dst=198.51.100.5:443
Without this log, you cannot attribute an external connection to a specific internal host. For investigations involving external victims or authorities, the NAT translation log is often subpoenaed.
Forensic pitfalls:
- Port-address translation (PAT) means hundreds of internal hosts share a single public IP. Only the combination of public port + time identifies the specific internal host.
- Some firewalls only log denied connections by default; allowed connections may have no log entry unless explicitly configured.
- Firewall rule names in logs are only meaningful if you have a copy of the ruleset at the relevant point in time.
Web Proxy and HTTP Logs
Enterprise web proxies intercept outbound HTTP/HTTPS and log URL-level detail. For HTTPS, a decrypting (SSL-inspection) proxy provides full URL and sometimes response content; a non-decrypting proxy logs only the CONNECT destination hostname.
Squid Access Log
Default format (/var/log/squid/access.log):
1747041001.234 312 192.168.8.215 TCP_MISS/200 48291 GET http://example.com/download.zip - DIRECT/93.184.216.34 application/zip
1747041002.001 0 192.168.8.118 TCP_DENIED/403 4096 CONNECT badsite.example.com:443 - NONE/- -
Fields: timestamp(epoch) elapsed client action/code bytes method url user peer/dest content-type
| Action code | Meaning |
|---|---|
TCP_MISS |
Cache miss, fetched from origin |
TCP_HIT |
Served from Squid cache |
TCP_DENIED |
Blocked by ACL |
CONNECT |
HTTPS tunnel (non-decrypting proxy) |
Filtering for large downloads (potential exfiltration or dropper staging):
awk '$5 > 10000000 {print $3,$6,$7,$5}' /var/log/squid/access.log | sort -k4 -rn
W3C Extended Log Format (IIS / Blue Coat / Zscaler)
W3C format is used by IIS, many commercial proxies, and cloud web gateways:
#Version: 1.0
#Date: 2025-05-12 09:22:00
#Fields: date time c-ip cs-method cs-host cs-uri-stem cs-uri-query sc-status sc-bytes cs(User-Agent)
2025-05-12 09:22:01 192.168.8.215 GET update.example.com /update/client.exe - 200 4194304 curl/7.88.1
2025-05-12 09:22:15 192.168.8.118 CONNECT c2.badactor.io:443 - - 200 8192 -
Forensic note on CONNECT: A CONNECT log entry with status 200 means the proxy established a tunnel but did not inspect the content. You know the destination but not what was transferred. A CONNECT entry followed by unusually large bytes transferred may warrant packet capture or SSL inspection review.
Evidentiary limits:
- HTTPS without SSL inspection shows only the destination hostname (SNI), not the path or query string.
- User-Agent strings are client-controlled and trivially spoofed.
- Proxy logs show what was requested, not what was done with the content.
VPN Logs
VPN logs record when remote users authenticate and what IP they receive. They are essential for attributing off-premises connections.
OpenVPN
Default log entries (server-side):
Mon May 12 09:30:00 2025 192.0.2.77:51234 TLS: Initial packet from [AF_INET]192.0.2.77:51234, sid=abc123
Mon May 12 09:30:02 2025 192.0.2.77:51234 VERIFY OK: depth=0, CN=jsmith
Mon May 12 09:30:02 2025 192.0.2.77:51234 [jsmith] Peer Connection Initiated with [AF_INET]192.0.2.77:51234
Mon May 12 09:30:02 2025 jsmith/192.0.2.77:51234 MULTI: Learn: 10.8.0.6/32 -> jsmith/192.0.2.77:51234
Mon May 12 09:30:02 2025 jsmith/192.0.2.77:51234 MULTI_sva: pool returned IPv4=10.8.0.6
Mon May 12 09:30:45 2025 jsmith/192.0.2.77:51234 Connection reset, restarting [0]
Mon May 12 09:30:45 2025 jsmith/192.0.2.77:51234 SIGUSR1[soft,connection-reset] received, client-instance restarting
Key fields:
| Field | Forensic value |
|---|---|
Client external IP (192.0.2.77) |
Public IP of the remote user |
Common Name (jsmith) |
Certificate identity — more reliable than password-based username |
Assigned internal IP (10.8.0.6) |
IP that will appear in internal logs during the session |
| Session start/end times | Defines the attribution window |
Finding sessions for a user:
grep 'jsmith' /var/log/openvpn.log | grep -E 'Initiated|Connection reset'
Geolocation anomaly triage: If a user’s VPN connection originates from an unexpected country or ASN, correlate against their normal login pattern. Note: VPN services, mobile carrier NATs, and cloud VM exit points make geolocation unreliable as a sole indicator.
Windows RRAS / Always-On VPN
Event IDs in Windows Event Log (Security):
| Event ID | Meaning |
|---|---|
| 20272 | IKE security association established (VPN connected) |
| 20274 | VPN connection established |
| 20275 | VPN connection disconnected |
| 20276 | Authentication failed |
RADIUS and 802.1X Logs
RADIUS authenticates network access: wired 802.1X, wireless WPA2-Enterprise, and VPN. RADIUS logs identify which user authenticated from which device at what time, enabling user-to-port and user-to-SSID attribution.
FreeRADIUS
Default log (/var/log/freeradius/radius.log):
Mon May 12 09:35:00 2025 : Auth: (1234) Login OK: [jsmith] (from client ap-lobby port 0 cli b8-27-eb-aa-11-22)
Mon May 12 09:47:12 2025 : Auth: (1235) Login incorrect: [baduser] (from client sw-floor3 port 48 cli 00-11-22-33-44-55)
Fields: timestamp, event type, username, NAS client, port (switch port or AP), calling-station-id (client MAC).
Key forensic questions RADIUS answers:
- Which user authenticated to this wireless SSID or switch port?
- At what time did they connect and disconnect?
- Which MAC address was used — does it match the expected device?
- How many failed authentications preceded a success (potential password spray)?
Detecting authentication failures (password spray):
grep 'Login incorrect' /var/log/freeradius/radius.log | \
awk '{print $9}' | tr -d '[]' | sort | uniq -c | sort -rn | head -20
Wireless Controller / AP Logs
Enterprise wireless controllers (Cisco WLC, Aruba, Juniper Mist) log association events that RADIUS does not capture:
- AP name and physical location of the access point a device associated with.
- RSSI (signal strength) — can approximate physical location.
- Roaming events between APs (device moved through building).
- Deauthentication and disassociation events (device left network or was kicked).
These logs are essential when a physical location for a network event is needed.
Evidentiary limits:
- RADIUS authenticates credentials, not possession of a device. A stolen credential can produce valid RADIUS logs under the victim’s username.
- EAP-TTLS/PEAP authentication protects the password in transit but the identity phase (outer identity) may not match the actual username logged.
- “Login incorrect” does not distinguish a fat-fingered password from a brute force attempt without examining the source and rate.
NetFlow and IPFIX
NetFlow (Cisco) and IPFIX (IETF standard) are flow-level summaries exported by routers and switches. They record who spoke to whom, how much data was transferred, and for how long — without capturing payload content.
A flow record represents one conversation:
| Field | Description |
|---|---|
src_addr |
Source IP |
dst_addr |
Destination IP |
src_port |
Source port |
dst_port |
Destination port |
protocol |
IP protocol number |
packets |
Packet count |
bytes |
Byte count |
start / end |
Flow start and end timestamps |
tcp_flags |
OR of all TCP flags in the flow |
nfdump queries NetFlow files exported by nfcapd:
# Top talkers by bytes in a time window
nfdump -r /var/cache/nfdump/ -t '2025/05/12.09:00:00-2025/05/12.10:00:00' \
-s record/bytes -n 20
# All flows from a suspicious host
nfdump -r /var/cache/nfdump/ 'src ip 192.168.8.215' -o long
# Large outbound transfers (potential exfiltration)
nfdump -r /var/cache/nfdump/ 'bytes > 100000000 and dst net not 192.168.0.0/16' -o long
Beaconing Detection
Malware C2 beaconing produces periodic small flows to the same destination at regular intervals. Characteristics:
| Characteristic | Typical beacon | Typical legitimate traffic |
|---|---|---|
| Inter-flow interval | Regular (e.g., every 60s ± jitter) | Irregular |
| Bytes per flow | Small and consistent | Variable |
| Destination | Fixed single IP or small pool | Diverse |
| Duration of activity | Hours to days | Minutes to hours |
# Find flows to a suspected C2 at regular intervals
nfdump -r /var/cache/nfdump/ 'dst ip 203.0.113.99' -o 'fmt:%ts %td %byt' | \
awk '{print $1}' | sort | uniq -c
Evidentiary limits: NetFlow does not capture payload, so you can prove a connection existed and how large it was, but not what was transferred. Exfiltration of 100MB and download of a software update are indistinguishable from NetFlow alone. MIME type from a proxy log or file signatures from a PCAP are needed for content attribution.
Suricata EVE JSON
Suricata is a network IDS/IPS that writes machine-readable JSON events to a single log file called eve.json. Unlike traditional alert-only IDS logs, Suricata also logs protocol metadata (DNS queries, HTTP requests, TLS SNI) regardless of whether a signature matches.
Default path: /var/log/suricata/eve.json
Each event has a event_type field:
| event_type | Content |
|---|---|
alert |
Signature match with rule metadata |
dns |
Every DNS query/response observed |
http |
HTTP request/response metadata |
tls |
TLS handshake metadata (SNI, cert subject, JA3) |
flow |
Completed TCP/UDP flow record |
fileinfo |
File observed in a flow (hash, name, MIME) |
ssh |
SSH client/server version strings |
smtp |
SMTP envelope metadata |
Querying EVE with jq
All alerts:
jq 'select(.event_type == "alert") | {ts: .timestamp, src: .src_ip, dst: .dest_ip, sig: .alert.signature}' \
/var/log/suricata/eve.json
HTTP requests from a host:
jq 'select(.event_type == "http" and .src_ip == "192.168.8.215") |
{ts: .timestamp, method: .http.http_method, url: (.http.hostname + .http.url), ua: .http.http_user_agent}' \
/var/log/suricata/eve.json
TLS SNI seen from a host (HTTPS destinations without decryption):
jq 'select(.event_type == "tls" and .src_ip == "192.168.8.215") |
{ts: .timestamp, sni: .tls.sni, ja3: .tls.ja3.hash}' \
/var/log/suricata/eve.json
JA3 fingerprint correlation: JA3 is a hash of TLS client hello parameters. Malware families often have distinctive JA3 hashes. Suricata logs the JA3 hash in every TLS event, allowing correlation even when the SNI or certificate changes.
Files observed (dropper staging, C2 download):
jq 'select(.event_type == "fileinfo") |
{ts: .timestamp, src: .src_ip, dst: .dest_ip, name: .fileinfo.filename, md5: .fileinfo.md5, size: .fileinfo.size}' \
/var/log/suricata/eve.json
Evidentiary limits:
- Suricata only sees traffic that passes through the interface it monitors. Traffic on VLANs or segments without a span/tap is invisible.
- Alert-based detection depends on signature coverage; novel malware may produce no alerts while still appearing in
dns,tls, andflowevents. - A Suricata alert shows a rule matched, not that an attack succeeded. Rule signature quality varies.
SMTP and Mail Server Logs
Mail server logs record the routing metadata for every message: envelope sender, recipient, relay hops, delivery status, and attachment count. They do not typically record message body content unless content inspection is explicitly configured.
Postfix
Postfix logs to syslog (usually /var/log/mail.log). Each message produces multiple entries tied by a queue ID:
May 12 09:40:01 mx1 postfix/smtpd[4321]: connect from mail.sender.example[203.0.113.5]
May 12 09:40:01 mx1 postfix/smtpd[4321]: A1B2C3D4E5F6: client=mail.sender.example[203.0.113.5]
May 12 09:40:02 mx1 postfix/cleanup[4322]: A1B2C3D4E5F6: message-id=<xyz@sender.example>
May 12 09:40:02 mx1 postfix/qmgr[1000]: A1B2C3D4E5F6: from=<alice@sender.example>, size=204800, nrcpt=1
May 12 09:40:03 mx1 postfix/smtp[4323]: A1B2C3D4E5F6: to=<bob@company.com>, relay=mail.company.com[10.0.0.25]:25, delay=2, status=sent (250 OK)
Reconstructing message routing by queue ID:
grep 'A1B2C3D4E5F6' /var/log/mail.log
Microsoft Exchange Message Tracking
Exchange writes CSV tracking logs to C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\Logs\MessageTracking\. Fields include:
date-time, client-ip, client-hostname, server-ip, source, event-id, internal-message-id, message-id, recipient-address, recipient-status, total-bytes, recipient-count, subject
Event IDs of forensic interest:
| Event ID | Meaning |
|---|---|
RECEIVE |
Server received a message |
SEND |
Server sent a message outbound |
DELIVER |
Message delivered to mailbox |
FAIL |
Delivery failed |
REDIRECT |
Message redirected (mail forwarding rule) |
Detecting auto-forwarding rules (data exfiltration via email):
grep 'REDIRECT' MessageTracking*.log | awk -F',' '{print $7,$10}' | sort | uniq -c | sort -rn
Persistent REDIRECT events for a single internal sender routing messages to an external address are a strong indicator of a compromised mailbox with an exfiltration forwarding rule.
SSH Logs
SSH authentication events are recorded by PAM and the sshd daemon to syslog. On most Linux systems this is /var/log/auth.log (Debian/Ubuntu) or /var/log/secure (RHEL/CentOS).
Authentication Events
May 12 09:45:01 server sshd[5678]: Failed password for jsmith from 203.0.113.42 port 44567 ssh2
May 12 09:45:03 server sshd[5678]: Failed password for jsmith from 203.0.113.42 port 44568 ssh2
May 12 09:45:05 server sshd[5679]: Accepted publickey for jsmith from 10.8.0.6 port 52341 ssh2: RSA SHA256:abc123...
May 12 09:45:05 server sshd[5679]: pam_unix(sshd:session): session opened for user jsmith by (uid=0)
May 12 09:45:45 server sshd[5679]: pam_unix(sshd:session): session closed for user jsmith
Key log events:
| Pattern | Forensic significance |
|---|---|
Failed password |
Brute force, credential spray |
Invalid user |
Scanning for valid usernames |
Accepted publickey |
Successful key-based login |
Accepted password |
Successful password login |
session opened / session closed |
Session duration |
Connection closed without session opened |
Port scan or early disconnect |
Count failed attempts per source (brute force triage):
grep 'Failed password' /var/log/auth.log | \
awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
Find successful logins after failures from the same source:
awk '/Failed password/{fail[$NF]++} /Accepted/{if(fail[$NF]>0) print "SUCCESS after",fail[$NF],"failures from",$NF}' \
/var/log/auth.log
Evidentiary limits:
- Public key authentication identifies possession of a private key, not a person. If the key is stolen or the agent is forwarded, the log entry is misleading.
session closeddoes not record what commands were run. Shell history (~/.bash_history) and process audit logs (auditd) are required for that.- SSH tunneling (port forwarding, SOCKS proxy) produces normal connection logs but the tunneled traffic is not logged by sshd.
Worked Investigation Scenario
Scenario: The security team receives an alert that 192.168.8.157 is serving files over unusual ports. Determine what happened, which device was involved, and what was transferred.
Step 1 — DHCP: identify the device
grep 'DHCPACK on 192.168.8.157' /var/log/syslog
# → 192.168.8.157 assigned to MAC aa:bb:cc:dd:ee:ff (hostname: fw-server) at 08:00:00
# → Lease valid for 86400 seconds (expires 09:00:00 next day)
Attribution: 192.168.8.157 = fw-server, MAC aa:bb:cc:dd:ee:ff during this window.
Step 2 — Firewall: what ports were open?
grep '192.168.8.157' /var/log/syslog | grep 'ACCEPT' | awk '{print $26}' | sort -u
# → DPT=12599 through DPT=12619 accepted inbound from 192.168.8.215
Finding: fw-server accepted connections on 21 ephemeral ports from 192.168.8.215.
Step 3 — Suricata HTTP events: what was requested?
jq 'select(.event_type == "http" and .dest_ip == "192.168.8.157") |
{ts: .timestamp, src: .src_ip, url: .http.url, bytes: .http.length}' eve.json | head -40
# → GET /download?name=firmware.bin&offset=<N>&size=<M> — dozens of chunked requests
Finding: 192.168.8.215 downloaded firmware.bin in chunks across 21 parallel TCP connections.
Step 4 — DHCP: identify the client
grep 'DHCPACK on 192.168.8.215' /var/log/syslog
# → MAC b8:27:eb:aa:11:22 (hostname: rpi-device) — Raspberry Pi OUI
Attribution: 192.168.8.215 = an IoT/embedded device (Raspberry Pi), rpi-device.
Step 5 — NetFlow: total bytes transferred
nfdump -r /var/cache/nfdump/ 'src ip 192.168.8.215 and dst ip 192.168.8.157' -s record/bytes
# → Total: ~4.3 GB over 45 minutes
Finding: 4.3 GB of firmware data was transferred to the Raspberry Pi.
Step 6 — DNS: did rpi-device contact any external hosts?
grep '192.168.8.215' /var/log/named/query.log | awk '{print $8}' | sort | uniq -c | sort -rn
# → wttr.in, httpbin.org, ifconfig.co, captive.apple.com (all consistent with IoT device startup)
Finding: No anomalous external DNS queries. The firmware retrieval was entirely internal.
Summary: A Raspberry Pi (rpi-device, 192.168.8.215) downloaded approximately 4.3 GB of firmware from fw-server (192.168.8.157) using a custom chunked HTTP download protocol on ports 12599–12619. All traffic was internal. The activity appears to be a legitimate firmware update mechanism, but the custom download server and large number of parallel connections warrant further review of fw-server’s purpose.
Log Source Quick Reference
| Log | What it proves | What it cannot prove |
|---|---|---|
| DHCP | IP → MAC → hostname at time T | User identity; MAC authenticity |
| DNS | Host queried a domain | What was returned; what was done with it |
| Firewall | Connection was allowed/denied | Whether the allowed connection succeeded at the app layer |
| NAT | Internal IP that used a public IP:port | Content of the connection |
| Proxy | URL visited; bytes transferred | Content if HTTPS without SSL inspection |
| VPN | User authenticated; received IP | What the user did after connecting |
| RADIUS | Username authenticated to this network segment | That the authenticated user was present at the device |
| NetFlow | Volume and duration of a conversation | Content; application |
| Suricata EVE | Protocol metadata; rule matches | That an attack succeeded; traffic on unmonitored segments |
| SMTP | Message routing and envelope | Message body (unless content inspection enabled) |
| SSH | Auth events; session open/close | Commands executed; tunneled traffic |