What a VPS abuse complaint means
Abuse mail about your VPS IP follows a fixed pipeline. Who reports, how the notice reaches you, what each category means, and how to answer in time.
What a VPS abuse complaint actually is
A VPS abuse complaint is a report about traffic that left your IP address, sent to the abuse contact published for that IP block, then passed to you by your host with a window to reply. The published contact belongs to the company that holds the address space, so the first person to read a report about your server is almost never you. Your host matches the IP and the timestamp to your account and forwards it.
The notice is no proof that you did anything on purpose. An IP address is the only identifier the reporter has. A compromised application sending spam at 03:00 produces the same report as a person sending spam at 03:00. This is why the reply is the part that matters. You are being asked what the source was and what you changed.
Who sends the report, and how does it reach your host
Every public IP block is registered with a regional internet registry (RIR): RIPE NCC, ARIN, APNIC, LACNIC or AFRINIC. Each registration publishes an abuse contact, and that is where reports go. You can read the same record the reporter reads:
whois 203.0.113.10 | grep -iE 'netname|descr|abuse'RIPE records carry an abuse-c: role object holding an abuse-mailbox: line. ARIN records carry OrgAbuseEmail:. Whatever address is published there receives the complaint, which is why a report about your server arrives at your host instead of in your inbox.
The party filing it is usually a machine. Four kinds cover almost everything you will meet:
- Automated scanners and honeypots. A machine records a connection attempt from your IP and files a report with the log excerpt attached.
- Feedback loops (FBL) run by mailbox providers. A recipient clicks the junk button and a copy of the message comes back in ARF (abuse reporting format), a structured mail format built for machines to parse.
- Copyright agents. They watch torrent swarms or crawl public URLs, then send a DMCA (digital millennium copyright act) notice naming a file, your IP, and a timestamp in UTC.
- Blocklist operators and network engineers, who send a short mail with the offending lines from their own logs.
Because most first reports are generated, an argument in reply achieves nothing. A fact achieves everything: what was running, and when it stopped.
Why does the notice arrive with a deadline
Your host is a tenant too. Its address space sits behind upstream carriers and inside reputation databases other people run. Reports that go unanswered raise the score against the whole block rather than your single address, so the deadline you receive is pressure being passed down. Read the window stated in the notice and treat it as real.
When something does happen to an unanswered case, it is usually a null route, meaning traffic to that one IP is dropped upstream, or a suspension of the instance. The trigger is normally silence, not the original event. What any specific host does, and when, is written in its own policy and in the notice itself. Those two documents are the only ones worth quoting, so do not act on what a forum claims a provider permits.
Outbound spam: why is my VPS sending mail I did not send
The report says your IP delivered mail to a spam trap, or that recipients marked your mail as junk. Four sources cover most cases: a web application with a mail form and no rate limit, a leaked SMTP credential now used by someone else, a mail server that relays for hosts it should not, and a stolen login on a newsletter application. Start with the queue, because a compromised sender is normally visible there:
sudo postqueue -p | tail -n 20
sudo postqueue -p | grep -c '^[0-9A-F]'A queue holding thousands of messages to addresses you do not recognise means the box is sending. Next, find out who authenticated:
sudo grep -o 'sasl_username=[^ ]*' /var/log/mail.log | sort | uniq -c | sort -rn | headOne account with a count far above the others is the leaked credential. If /var/log/mail.log does not exist, the system has no rsyslog installed and the same lines are in the journal instead: sudo journalctl -t postfix --since '2 days ago'.
If nothing authenticated, the sender is a local process. Check the relay rules and the open connections:
sudo postconf -n | grep -E 'mynetworks|inet_interfaces|relay'
sudo ss -tnp state established '( dport = :25 )'A stock Debian or Ubuntu Postfix does not relay for strangers. It becomes an open relay when mynetworks is widened by hand to a whole hosting subnet, because every other tenant on that subnet is then trusted to send through you. Any connection to port 25 owned by a process that is not your mail server is a script sending mail on its own, which is what a compromised PHP application usually does.
Stop the flow before you investigate, and keep the evidence:
sudo systemctl stop postfix
sudo tar czf /root/mailqueue.tgz -C /var/spool postfixsudo postsuper -d ALL empties the queue, and it also destroys the record of what was sent, so take the copy first. Then rotate every credential the application holds, update the application, and look for what the intruder left behind. A spam incident and a compromise are the same event most of the time, so work through the recovery steps for a hacked VPS rather than only clearing the queue.
Port scanning and brute force: what a compromised container looks like
This report carries lines from another operator's logs, and they look like this:
sshd[2841]: Invalid user admin from 203.0.113.10 port 51992The cause is almost always a service you believed was firewalled. Docker is the frequent one. Publishing a port with -p 6379:6379 writes rules into the DOCKER-USER and nat chains, and those are evaluated before ufw's rules, so ufw deny 6379 does not block it and the database answers the whole internet.
sudo ss -ltnp
sudo iptables -S DOCKER-USER
docker psAnything in ss -ltnp bound to 0.0.0.0 or [::] is listening on the public address. Publish to the loopback address instead, -p 127.0.0.1:6379:6379, when only the host needs to reach it. Where a database should live in the first place is a separate decision, and running the database in Docker or on the host covers that trade.
To see whether your own box is scanning right now:
sudo ss -tnp state syn-sentMany half-open connections to many different destinations is an outbound scan in progress. A kernel log filling with nf_conntrack: table full, dropping packet says the same thing from another angle: something is opening far more connections than this server has any reason to open.
Rebuild a compromised container rather than cleaning it. You cannot prove what else changed inside it, so rebuild from an image you trust, restore only data you trust, and rotate the keys that container held.
Copyright notices: which file did they actually see
A DMCA notice names a URL or a torrent info hash, your IP, and a timestamp in UTC. Two causes cover nearly all of them: a directory the web server lists publicly with media files in it, and a torrent client still seeding after the download finished.
Match the timestamp against the access log. The nginx combined log format puts the status in field 9 and the request path in field 7:
sudo grep '14/Aug/2026:03' /var/log/nginx/access.log | awk '{print $9, $7}' | sort | uniq -c | sort -rn | headBefore you conclude that nothing was served, check the clock. The notice is in UTC and your logs use the server's timezone, so an offset of a few hours sends you searching the wrong window and reporting a false negative:
timedatectl
sudo timedatectl set-timezone UTCThen fix the cause. Remove or restrict the file, turn off directory listing with autoindex off; in the nginx location block, and bind the torrent client to an interface that is not the public one. Reply naming the file, the change, and the time you made it. If you believe the claim itself is wrong, that is a legal question between you and the sender, and the notice states how to dispute it. Your host is not the party that decides it, so a ticket arguing the merits goes nowhere.
Blocklist listings: why did my outbound mail stop working
This one often arrives with no mail to you at all. Outbound mail simply stops being accepted, and the bounce carries the reason:
554 5.7.1 Service unavailable; Client host [203.0.113.10] blocked using zen.spamhaus.orgCheck a listing by reversing the four octets of the IP and querying the list's zone:
dig +short 10.113.0.203.zen.spamhaus.orgAn empty answer means you are not listed there. A 127.0.0.x answer means you are, and the final octet says which sublist matched. An answer in the 127.255.255.x range means the query was refused rather than answered, usually because it went out through a large public resolver, which the free service does not serve. Run it again from the server's own resolver to get a real result.
Delisting happens on the list operator's site, not through your host, and it only holds if the source is fixed first, because the trap that listed you lists you again on the next message. Two other things decide whether mail flows afterwards. Your PTR record, the reverse DNS name for the IP, is controlled by your host, so ask them to set one that resolves back to the same address and use that name as your HELO. And an address recycled from a previous tenant can carry a history you did not create, which is worth asking about before you spend a week rewriting DNS. Getting the SPF (sender policy framework) and DKIM (domainkeys identified mail) records right, plus the DMARC policy that ties them together, is covered end to end in the guide to running your own mail server with Mailcow.
Relay infrastructure, where abuse mail is part of the job
If you run a Tor exit node, a public VPN, or a proxy for other people, complaints about traffic you did not generate are a normal running cost. The work is looking visibly like a relay rather than like a compromised box. Set reverse DNS to a descriptive name, serve a short notice page on port 80 that explains what the address is, answer abuse mail quickly with the same explanation, and use whatever policy the software offers to drop the ports that generate the most reports. Run it on its own IP address, and ideally its own instance, so a null route on that address does not take your web application down with it. Ask your host before you start, because what is allowed varies by company and sometimes by IP block, and that is a question for them rather than for a forum thread. Running a Tor exit node on a VPS goes through the exit policy and the notice page in detail.
How to answer so the ticket closes
- Publish a contact a person reads. RFC 2142 makes
abuse@andpostmaster@on your domain the addresses reporters try first. Host that mailbox somewhere other than the server it protects, because a suspended instance cannot deliver the notice telling you it was suspended. - Keep logs long enough to answer at all. A report about traffic twelve days ago is unanswerable if the log rotated after seven. Check
journalctl --disk-usage, setMaxRetentionSec=90din/etc/systemd/journald.conf, then runsudo systemctl restart systemd-journald. Web and mail logs rotate on their own schedule under/etc/logrotate.d/. - Keep the server on UTC, so a timestamp in a report matches a timestamp in your logs with no arithmetic in between.
- Separate what attracts complaints from what you cannot lose. Mail on one address, the web application on another, relay services on their own instance. Action taken against an IP is action taken against everything behind it.
- Answer inside the window even when the investigation is unfinished. A holding reply with a time in it is a complete answer for round one.
A first reply that closes most tickets is short and specific:
Received, thank you. Confirmed at 09:14 UTC.
Source: a contact form in our web app that allowed unauthenticated sending.
Action: form disabled, Postfix stopped, all SMTP credentials rotated 09:31 UTC.
Evidence: mail queue and logs preserved for 90 days if you need them.
Next: patched app redeployed by 18:00 UTC today. I will confirm here.Say what you know, and say what you have not worked out yet. Silence reads as an unmaintained server, and the escalation path exists for unmaintained servers. Whether any of this work is yours at all depends on the product you bought, which is the practical difference between managed and unmanaged VPS hosting. On an unmanaged plan the tenant is the security team.
What this looks like when it goes well
An abuse complaint is a routing problem before it is anything else. A report about an address goes to the party responsible for that address, and gets passed down to the person who can fix it. The parts you control are your contact address, your log retention, how your services are split across IPs, and how fast you write back. Get those right and most notices end after one exchange. The same habits settle the larger question of whether VPS hosting is safe, because a server nobody is watching is the one that ends up in somebody else's logs.
FAQ
Does an abuse complaint mean my VPS was hacked?
Not by itself, but that is the first thing to rule out. The report proves only that traffic left your IP. Outbound spam and port scanning come from a compromised application or container far more often than from the account owner, so check the mail queue with sudo postqueue -p and the listening sockets with sudo ss -ltnp before anything else. Copyright and blocklist notices are different in character: those usually point at something you are running on purpose.
How long do I have to reply to an abuse notice?
The window is stated in the notice you received, and it varies by host and by category. Copyright and spam-trap reports tend to carry the shortest ones. Treat the stated time as real and send a short holding reply before it expires, even while you are still tracing the cause. What matters to the person handling the ticket is that a human is on it and the traffic has stopped.
My IP is on a blocklist. Can my host remove it?
No. Delisting is done by the operator of that list, on its own site, and your host has no control over their database. Your host does control the PTR record, the reverse DNS name for your IP, which is a separate request worth making at the same time. Fix the sending problem before you request delisting, because the spam trap that listed you will list you again on the next message.
Do I have to tell my host what actually happened?
You have to tell them enough to close the ticket: what the source was, and when it stopped. You do not owe a forensic report or your users' data. A vague reply is worse than a small one, because a handler who cannot see what changed has no reason to treat the case as resolved.
Can I ignore an automated report from a scanner?
No. Automated reports are counted, and repeated reports about one IP raise the score against your host's whole address block, which is what turns a small case into an escalation. Your reply can be one paragraph. The automated reporter usually never reads it, but the person handling the ticket at your host does, and that is the reader deciding what happens to your instance.