Restrict Employee Clock-In by IP Address in WordPress

If you run on-site staff, you already know the failure mode: someone clocks in from the bus, or a coworker punches them in from the break room. The fix that actually holds is simple to say and a little fiddly to set up right — restrict employee clock-in by IP address in WordPress, so a punch only counts when it comes from your office network.

This guide walks through how to do that properly: the difference between your public IP and your LAN address (the part people get wrong), how to build an allowlist with exact IPs, CIDR blocks, and ranges, how to turn the lock on per employee, and — the part that matters most — making sure the rule is enforced on the server, not just logged after the fact.

We’ll use Punchwell for the concrete steps, since its office-IP lock is the flagship feature. The concepts apply regardless of which tool you use.

Why IP, and not just GPS?

Most SMB time clocks that promise to stop buddy punching do it with GPS geofencing only. That’s not nothing — but GPS needs a phone app, and a location can be faked from a couch with a spoofing tool. An office-IP check works differently: to clock in, the device has to actually be on your network, reaching the internet through your office’s connection. You can’t fake that from home.

The honest version: treat GPS as a deterrent, and the IP lock as the hard control. The strongest setups use both — IP as the wall, GPS as an extra signal — which is why Punchwell ships GPS geofence, kiosk, and mobile punch alongside the IP lock, so you can be softer or stricter per site.

Step 1 — Find your office’s PUBLIC IP (not the LAN address)

This is the single most common mistake, so it’s worth slowing down on.

Your office router gives each device a private/LAN address — something like 192.168.1.x or 10.0.0.x. That address only means anything inside your building. When a device talks to your WordPress site, the site never sees the LAN address. It sees your office’s public IP — the single address your internet provider assigns to your whole office.

So the allowlist has to use the public IP. If you enter 192.168.x.x, the lock will never match anything and every punch will be refused.

To find it, sit at a computer on the office network and visit any “what is my IP” page, or just use the helper inside the plugin. Punchwell puts a one-click “Use this IP” button on every IP-entry screen — it reads the public IP of the request you’re making right then, so as long as you’re configuring it from the office, it grabs the correct address for you.

One caveat to check with your ISP: is your office IP static or dynamic? Many small-business connections get a dynamic IP that can change. If yours does, that’s exactly what CIDR blocks and ranges (next step) are for — and it’s worth asking your provider whether a static IP is available, since it makes this setup permanent.

Step 2 — Build the allowlist: exact IPs, CIDR, and ranges

An allowlist is just the set of addresses a punch is allowed to come from. Punchwell accepts three formats, in both IPv4 and IPv6:

  • Exact IP203.0.113.10. Simplest case: one office, one fixed public IP.
  • CIDR block203.0.113.0/24. This allows a whole contiguous range in one line instead of listing each address. A /24 covers 256 addresses (.0 through .255). Useful when your ISP assigns you a block, or your address moves around within a known range.
  • Address range — a defined start-to-end span, for when your allowed addresses don’t fall neatly on a CIDR boundary.

If your office IP is dynamic but stays within a band your ISP gives you, a CIDR block or range covers the whole band so a normal IP change doesn’t lock anyone out.

Three scopes, all unioned (it only ever widens access)

Punchwell lets you set allowed IPs at three levels, and it combines them rather than making them compete:

  1. Company-wide — the default allowlist for everyone.
  2. Per-office — each office location can carry its own IPs, so a second branch’s network is allowed for the people who work there.
  3. Per-employee — an “Additional allowed IPs” field on an individual’s profile, for the one person who legitimately works from a fixed second location.

These are unioned (widen-only): adding an IP at any level only ever adds permitted addresses, it never removes them. That means you can’t accidentally lock out your whole company by editing one person’s profile — a useful property when you’re tuning this live. (If you’re on a single-office setup, this is invisible; the global list is all you need.)

Step 3 — Turn the lock on, per employee

Here’s where Punchwell differs from the typical “global on/off” switch. The lock is a per-employee flag: on each person’s profile you mark whether they’re “office-only.” Flagged employees can punch in or out only from an allowlisted address; everyone else clocks in normally.

That granularity matters for real teams. Your on-site cashiers and floor staff get locked to the building. Your bookkeeper who works remote two days a week, or a manager covering another branch, clocks in from anywhere. One setting per person, no compromise between the two.

For onboarding, there’s a default-lock-new-employees option (applied when a WordPress user is created) and a lock-by-role option, so you don’t have to remember to flip the flag for every new hire.

For comparison: WP ERP, the closest WordPress competitor, offers an attendance IP whitelist that is global-only — it’s everyone or no one. There’s no way to lock the cashiers but not the remote bookkeeper. (Approximate, as of June 2026; confirm current capabilities.)

Step 4 — Confirm it’s enforced SERVER-SIDE (this is the whole point)

A lock that only records an off-site punch isn’t a lock — it’s a report you read after payroll already went out. The thing to verify in any tool is whether the rule runs on the server, at the moment of the punch, and refuses the punch when the address doesn’t match.

Punchwell does this in its punch-validation code (Hrm_Attendance::common_punch_validation()): when a flagged employee tries to punch from an address that isn’t on the unioned allowlist, the server rejects the punch outright. Nothing client-side can talk it out of that, because the decision happens after the request reaches your WordPress install. It’s also direction-aware — an optional clock-in time window restricts when punches are accepted but won’t block someone from clocking out.

You also get a few controls around the hard refuse:

  • Enforcement modesBlock (hard refuse), Warn, or Flag. Block is the real control; warn/flag let you observe behavior during a rollout without locking anyone out. (Be aware: in Punchwell, warn and flag behave the same way by design — neither blocks; they record the attempt rather than tagging the row.)
  • Blocked-attempt email — HR gets a heads-up when an off-site punch is refused, so a pattern of attempts is visible.

Step 5 — Test before you trust it

Don’t take it on faith. Two quick checks:

  1. On the office network, with a flagged employee, punch in and out. It should work normally.
  2. Off the network — tether a phone to cellular, or use a connection that isn’t your office — and try to punch as that same employee. It should be refused.

If both behave as expected, the public IP is right and the lock is live. A good first rollout is to run in Warn mode for a week, watch the blocked-attempt emails to confirm the right people are matching, then switch to Block.

A note on self-hosting and your data

Because Punchwell is self-hosted, all of this lives inside the WordPress site you already run — employees are WordPress users, timesheets are rows in your own database, and there’s no cloud holding your data and no data call-home (verified — the free version makes zero outbound calls; Pro’s only outbound call is license validation, never your data). For privacy-sensitive shops — clinics, dental, agencies — that’s often the deciding factor, separate from the IP feature itself.

It’s also flat-priced: per site, never per seat. The free core on WordPress.org includes basic single-office IP locking; the full per-employee/per-office depth with CIDR and ranges is in Pro at $99/year per site, unlimited employees. For a 25-person shop, per-head SaaS clocks run roughly $1,500–2,100/year (approximate, as of June 2026 — confirm current rates with each vendor). See pricing for the full breakdown.

Quick reference

Task What to do
Find the address to allow Use your office’s public IP, not 192.168.x / 10.x
One fixed office IP Add an exact IP (203.0.113.10)
A whole block / changing IP Add a CIDR (203.0.113.0/24) or a range
Second branch Add IPs at the per-office level
One remote person Add their IP to per-employee “Additional allowed IPs”
Turn it on Flag the employee as office-only (or default-lock new hires)
Make it real Confirm Block mode = refuses the punch server-side
Roll out safely Start in Warn, watch blocked-attempt emails, then Block

The short version

To restrict employee clock-in by IP address in WordPress: allow your office’s public IP (exact, CIDR, or range), flag the employees who must be on-site, and make sure the tool refuses off-site punches server-side rather than just logging them. That last part is what actually stops buddy punching.

If you’re setting this up, the IP clock-in lock feature page walks through every option, and the security overview covers how punches are validated. Still running the old, abandoned plugin? Your records carry over — see the migration guide.

Punchwell, by Sturdyhaus, is an independent, third-party maintained GPL fork of the “WP Human Resource Management” plugin. Not affiliated with, endorsed by, or sponsored by wpspear, weDevs, or the original author; the original plugin and any competitor names are referenced descriptively only. Competitor pricing is approximate, as of June 2026 — confirm current rates with each vendor.


Punchwell is an independently maintained GPL fork. Not affiliated with the original “WP Human Resource Management” plugin or its authors. Competitor names and figures are nominative and approximate (as of the date noted) — confirm current rates.