Check my connection

Guides · Investigate an IP

I found an unknown IP in my server logs. What should I do?

You open your access log to look for something else, and there it is: an address you've never seen, hitting your site at four in the morning. Here is how to work out, in about ten minutes, whether it's worth a second thought.

Start with the reassuring part. A server on the public internet is visited by automated traffic all day, usually long before any person finds it. Crawlers index pages. Research projects scan every address on the internet to map what's out there. Other scripts try the same few doors on millions of sites, hoping someone left one open. Seeing addresses you don't know is normal. The question is never “is this IP bad?” but “what did it try, and did it work?”

Find the lines

WordPress doesn't keep a visitor log of its own. The record is your web server's access log, and where it lives depends on your hosting:

To pull every line for one address on Linux or macOS, search for it with a space after it. Without the space, a search for 203.0.113.4 would also match 203.0.113.45:

grep -F '185.220.101.1 ' /var/log/nginx/access.log
zgrep -F '185.220.101.1 ' /var/log/nginx/access.log.*.gz   # older, compressed days

To see which addresses visit most, count the first field:

awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

On Windows, PowerShell does the same search:

Select-String -Path 'C:\inetpub\logs\LogFiles\W3SVC1\*.log' -Pattern '185.220.101.1' -SimpleMatch

IIS writes its fields in a different order from Apache and nginx; the #Fields: line at the top of each file tells you which column is the client address (c-ip).

Is that really the visitor's address?

Check this before anything else. If your site sits behind a CDN or proxy such as Cloudflare, your server may be logging the CDN's address for every request, not the visitor's. If the same few addresses appear on every line and they belong to your CDN, you're looking at the CDN. Your server needs to read the original address from the header the CDN adds (CF-Connecting-IP for Cloudflare, for example; Apache's mod_remoteip and nginx's real_ip module do this). Until then, blocking by IP on the server would block the CDN, and everyone with it.

Read one line

Most Apache and nginx servers write the “combined” format. Here is one line from the example below, split into its parts:

185.220.101.1 - - [05/Nov/2026:09:31:07 +0000] "POST /wp-login.php HTTP/1.1" 200 6832 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
185.220.101.1
The address that connected to your server. For a completed web request this is hard to fake, though it may belong to a VPN, Tor or a cloud server rather than to the person behind it.
- -
Identity and user name. Almost always empty.
[05/Nov/2026:09:31:07 +0000]
When it happened, with the time zone offset.
"POST /wp-login.php HTTP/1.1"
What it asked for. POST sends data, here a user name and password.
200
Your server's answer. This is the most important field on the line.
6832
Bytes sent back.
"-"
Referrer: the page that linked here. Sent by the client, so it can say anything.
"Mozilla/5.0 …"
User agent: what the client claims to be. Also sent by the client, so also unproven.

Keep that last point in mind: the address is evidence, the user agent is a claim.

A worked example: one morning on a small WordPress blog

These twelve lines are a typical half hour on a small blog. We replaced the one ordinary reader's address with a documentation address (203.0.113.45, reserved for examples), so no real person appears here. The other addresses are public infrastructure.

The example log (12 lines)
203.0.113.45 - - [05/Nov/2026:09:14:02 +0000] "GET /2026/10/back-up-your-photos/ HTTP/1.1" 200 18342 "https://www.google.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
203.0.113.45 - - [05/Nov/2026:09:14:03 +0000] "GET /wp-content/themes/twentytwentyfive/style.css HTTP/1.1" 200 4120 "https://example.com/2026/10/back-up-your-photos/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
66.249.66.1 - - [05/Nov/2026:09:15:40 +0000] "GET /2026/09/router-settings/ HTTP/1.1" 200 21004 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
167.94.138.35 - - [05/Nov/2026:09:17:11 +0000] "GET / HTTP/1.1" 200 15233 "-" "Mozilla/5.0 (compatible; CensysInspect/1.1; +https://about.censys.io/)"
3.5.140.1 - - [05/Nov/2026:09:20:55 +0000] "GET /.env HTTP/1.1" 404 548 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
3.5.140.1 - - [05/Nov/2026:09:20:55 +0000] "GET /wp-config.php.bak HTTP/1.1" 404 548 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
3.5.140.1 - - [05/Nov/2026:09:20:56 +0000] "GET /wp-content/uploads/2026/11/cache.php HTTP/1.1" 404 548 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
185.220.101.1 - - [05/Nov/2026:09:31:07 +0000] "POST /wp-login.php HTTP/1.1" 200 6832 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
185.220.101.1 - - [05/Nov/2026:09:31:09 +0000] "POST /wp-login.php HTTP/1.1" 200 6832 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
185.220.101.1 - - [05/Nov/2026:09:31:12 +0000] "POST /xmlrpc.php HTTP/1.1" 200 4272 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
185.220.101.1 - - [05/Nov/2026:09:31:15 +0000] "POST /wp-login.php HTTP/1.1" 200 6832 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
40.77.167.10 - - [05/Nov/2026:09:40:28 +0000] "GET /robots.txt HTTP/1.1" 200 67 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"

We pasted the log into iplover's log checker. It found six addresses and checked the five public ones against the public lists on our server; the log itself stayed in the browser. This is the result table it showed on 9 November 2026:

IP addressLinesCategoryNetwork type
185.220.101.14Tor exit nodesTor exit node
3.5.140.13Cloud and hostingHosting, cloud or data center
203.0.113.452Private or reservedPrivate or reserved address (not checked)
66.249.66.11GooglebotNot identified
167.94.138.351Internet scannersNot identified
40.77.167.101BingbotNot identified

Two columns, two questions. Category says what the address is known for: a crawler, a scanner, Tor, a cloud provider. Network type says what kind of network it belongs to, as far as the public lists show. “Not identified” there only means no list covers it; it's no verdict on the address.

Lists change every day, so if you run the same example later, a result can differ. Here is what each group means for this site.

The reader: 203.0.113.45

Two requests a second apart: a blog post, then the theme's stylesheet, with Google as the referrer and an ordinary Chrome user agent. That's a person who searched, clicked and read. In your own log, a real visitor's address would show up as an internet provider. Nothing to do.

The crawlers: 66.249.66.1 and 40.77.167.10

Googlebot fetched a post, Bingbot read robots.txt. The log checker found both addresses in the lists the search engines publish, which is why it names them; it never goes by the user agent alone. You can confirm Googlebot yourself with two DNS lookups, as Google recommends: the reverse lookup must end in googlebot.com, google.com or googleusercontent.com, and the forward lookup of that name must return the same address.

host 66.249.66.1
host crawl-66-249-66-1.googlebot.com

If you'd rather a crawler visited less, say so in robots.txt. Blocking real search engines removes you from their results.

The scanner: 167.94.138.35

Censys scans the whole internet and makes the results searchable for security teams and researchers. It asked for your homepage and left. This is noise, not an attack. You can block scanners if the lines annoy you, but they don't put your site at risk.

The impostor: 3.5.140.1

This is the line that should make you look twice. The user agent says Googlebot, but the address belongs to Amazon Web Services, not Google. Google's crawlers don't run on Amazon's cloud. Anyone can type “Googlebot” into a user agent.

Then look at what it wanted: /.env, /wp-config.php.bak and a .php file inside the uploads folder. That's a shopping list of secrets: .env files and backup copies of wp-config.php often contain database passwords and keys, and a PHP file in uploads would be a backdoor someone left earlier. All three got 404. Nothing was there, so nothing was taken.

Make sure that stays true. Ask for those paths yourself and check that the answer is a 404 or 403, never a 200:

curl -I https://example.com/.env
curl -I https://example.com/wp-config.php.bak

The password guesser: 185.220.101.1

Four POST requests in eight seconds, three to /wp-login.php and one to /xmlrpc.php. That's someone trying passwords. The XML-RPC endpoint is a favourite because one request can carry many guesses.

Every answer was 200, which is good news. When a WordPress login fails, the login page is shown again with an error, and that page is a 200. A successful login is answered with a redirect to the dashboard, which shows up in the log as a 302. No 302, no way in.

The address is a Tor exit relay, shared by many people. Blocking it would stop these four requests, but the next attempt simply arrives from another exit, or from a cloud server. The Tor Project itself notes that some Tor users may be legitimate visitors to your site. The lasting fix is on your side, and it's further down.

Verdict for this morning: nothing got in. Two things are worth fixing, though: harden the login, and confirm the secret files really aren't reachable.

If you see this, do this

The same reasoning works for any line. Find the row that matches what you're looking at:

What you see in the logWhat it meansWhat to do
Ordinary pages, 200, a browser user agent, a search engine as referrerA visitorNothing.
A crawler the log checker names (Googlebot, Bingbot and so on)A real search engine or known botNothing. Use robots.txt to limit it.
“Googlebot” or “bingbot” in the user agent, from an address that isn't theirsA fake crawlerTreat it as an unknown bot. Block it if it bothers you.
Requests for /.env, backups, phpmyadmin and the like, all 404A scanner looking for mistakesCheck those paths return 404 for you too. Otherwise, nothing.
The same kind of request answered with 200A secret file was readableAct now. Assume it was copied: change every password and key it contained (database password, WordPress salts, API keys), then remove the file.
Many POSTs to /wp-login.php or /xmlrpc.php, answered 200Password guessing that failedHarden the login (below).
A POST to /wp-login.php answered 302, from an address you don't recogniseSomeone logged inCheck Users for accounts you didn't create, change all admin passwords, use Log Out Everywhere Else on your profile, and look for plugins or themes changed recently.
A 200 for a .php file inside /wp-content/uploads/Possibly a backdoor that's already thereUploads should never contain PHP. Treat the site as compromised: ask your host for help and restore from a backup you know is clean.
Hundreds of requests a minute from one network, and the site slows downAn aggressive botRate-limit it at your CDN or firewall, or block the range.

Harden the login

Password guessing never stops, so make it pointless rather than trying to block every address:

When blocking an address does make sense

Blocking is worth it for one persistent source that's wasting resources, such as a single cloud server hammering your site. It's a weak defence against everything else, because bots change address freely. If you do block one, here's how. (The log checker's Copy a block list box writes these lines for you, for the categories you tick.)

Apache 2.4, in the site configuration or .htaccess:

<RequireAll>
    Require all granted
    Require not ip 203.0.113.45
</RequireAll>

nginx, inside the server block:

deny 203.0.113.45;

Behind Cloudflare or another CDN, block at the CDN instead (Cloudflare calls this IP Access Rules or WAF custom rules; menu names change from time to time). Your server only sees the CDN's addresses unless you've set it up to read the visitor's.

What an IP address can't tell you

An address points to a network, not a person. It can be shared by thousands of people behind one provider, a VPN or Tor. It can belong to someone else next week. Its location is an estimate, often just the provider's nearest city. So don't treat an address as an identity, and don't try to track anyone down from it. Our guides on what someone can do with an IP address and whether an IP reveals a home address go into why.

If an address keeps attacking you, the useful contact is the network that runs it. The IP lookup shows the owner and its abuse address from the official registries. Expect a reply for persistent abuse from one server, not for a single scan. If you've lost data or money, report it to the police in your country as well.

Sources

Official documents we used to check the facts in this guide.