---
title: "IP ranges, auto-ban, lockout, tarpits, sending limits, send-as and password storage"
url: https://www.hmailserver.co.uk/topic/28239/ip-ranges-auto-ban-lockout-tarpits-sending-limits-send-as-and-password-storage
author: "Progressiverobot"
published: 2026-09-27T19:21:13.731Z
updated: 2026-09-27T19:21:13.731Z
category: "Guides & tutorials"
tags: ["security","smtp","administration","rest-api","control-panel"]
site: hMailServer Community Forum
---

# IP ranges, auto-ban, lockout, tarpits, sending limits, send-as and password storage

*Written for 6.3.4. hMailServer 6.3.7 (17 October 2026) is a security release that bears on the send-as and sign-in sections here. An authenticated submission is now DKIM-signed as another domain hosted here only when its account may send as the address its From names (its own address, an alias pointing at it, a mailbox that granted it the post right, an address it proved, or a masked address of its own, the addresses the send-as table below lists); otherwise the mail is still accepted and sent, unsigned as that domain, so give such an account the alias or the grant before upgrading. A domain's or an account's rule replies only from an address its owner may send as. SMTP, POP3 and ManageSieve refuse a SASL PLAIN sign-in that asks to act as another account; with SRS on, mail to an SRS address this server handed out is held to the relay rules unless it is a bounce; the IMAP and POP3 listeners can take the client's address from a PROXY protocol header as the SMTP listener does, each from a list of peers of its own, both off by default; and the Control Panel's IP ranges page, which could show no list of ranges at all, is fixed. See [the 6.3.7 announcement](/topic/28277). hMailServer 6.3.8 (2 November 2026) is a security release that bears on the auto-ban, the lockout and the IP ranges here. The auto-ban saves the IP range it adds under a name of its own, the user name cut so that the name and its suffix fit in the 100 characters a range's name holds, so that it bans the address: up to 6.3.7 a second or later ban for a long user name could be refused (HM6099) and the address given a whole new set of attempts, and now an address's counted failures are cleared only once its range is saved. A sign-in's name is matched to its account as the per-name lockout counts it, so a mail client that signs in with another spelling of the account's address than the stored one, in more than the case of the letters A to Z, or with white space at either end, may no longer sign in, and each such try is counted as a failure: correct the name in the client. With the web services listener on, an address whose IP range allows none of SMTP, POP3 and IMAP, an auto-ban's or one of your own, is now refused there too, before the TLS handshake, loopback and the addresses in `WebServicesTrustedProxies` apart; such a range of your own closes to its addresses ACME's http-01 validation when this listener answers it, MTA-STS, CalDAV, CardDAV, Autodiscover, autoconfiguration and the Web Key Directory, so before upgrading check that the certificate authority, the sending MTAs and these services' clients do not come from one. See [the 6.3.8 announcement](/topic/28278).*

This topic covers who may use this server and how hard it is to abuse it. Know this first: **only the IP ranges and auto-ban work out of the box; every other brake here is off until you set it.** Until you do, nothing else stops a botnet spending one guess per address, or a stolen password sending thousands of messages. The secure defaults of a new installation, TLS for sign-in and compromised-account detection are in [Hardening a public mail server](/topic/28241).

### Where each one is set

Since 6.3.4 the database is the settings store, and for a key it holds, a `[Settings]` line edited in `hMailServer.ini` changes nothing; on 6.3.3 these keys were lines of the file, applied at the next start. The store, and when a save takes effect, are in [the settings topic](/topic/28222).

| What | Kept in | Set with | Takes effect |
|---|---|---|---|
| IP ranges | the database | Control Panel **Access & abuse protection → IP ranges**; the Control Deck's IP ranges view; `/api/v1/ipranges`; `hmctl iprange`; COM `Settings.SecurityRanges` | at once |
| Auto-ban's four settings | the database | Control Panel **Access & abuse protection → Auto-ban**; the Deck's settings; `PUT /api/v1/settings`; COM | at once |
| Lockout, tarpits, rate limit, send-as check, hashing, policy | the settings store, under their `[Settings]` names | Control Panel; `PUT /api/v1/settings/ini/{name}`; `hmctl ini set <name> <value>`; COM `Settings.SetIniSetting`; on Linux `hmailserver --set-setting NAME=VALUE` | when saved |
| `[SendingLimits]`, `[SendingLimitsOverrides]`, `PasswordPepper` | `hMailServer.ini` only | the file, by hand or through the Control Panel (below) | sending limits within seconds; the pepper after a restart |

The Control Panel and COM are Windows-only. Of these `[Settings]` keys the Deck edits only `SmtpTarpitCount` and `SmtpTarpitDelaySeconds`. A value set with `hmailserver --set-setting` while the service runs waits for the next save, reinitialise or restart.

### IP ranges: priority and the relay grid

When a client connects, every range containing its address is found and **the highest priority wins**. The shipped ranges are *Internet* (priority 10, `0.0.0.0`–`255.255.255.255`) and *My computer* (priority 30, `127.0.0.1`); a range added on the Control Panel's page starts at 15, so a narrow range sits in front of *Internet* without editing it.

At every `RCPT TO` two decisions are made, in order: may this combination be delivered at all (if not, `550 Delivery is not allowed to this address.`), and must the client authenticate first (if so, `530 SMTP authentication is required.`). "Local" and "remote" describe the **addresses**, not the client: an address is local when its domain is a hosted active domain or a route says so.

| Combination | REST fields: allowed / auth required | *Internet* | *My computer* |
|---|---|---|---|
| Local → local | `deliver_local_to_local` / `require_auth_local_to_local` | allowed, **auth required** | allowed, no auth |
| Local → remote | `deliver_local_to_remote` / `require_auth_local_to_remote` | allowed, **auth required** | allowed, no auth |
| Remote → local | `deliver_remote_to_local` / `require_auth_remote_to_local` | allowed, no auth | allowed, no auth |
| Remote → remote (relay) | `deliver_remote_to_remote` / `require_auth_remote_to_remote` | allowed, **auth required** | allowed, **auth required** |
| Anti-spam, anti-virus | `spam_protection`, `virus_protection` | on | on |
| Require TLS for auth | `require_tls_for_auth` | on in a new 6.3.4 installation; otherwise as the server had it | off |

**Remote → remote is the open-relay box.** Both shipped ranges allow it with authentication required, even from 127.0.0.1, so a client that has not signed in gets `530`; a range that does not allow it at all gets `550`. The Control Panel's Server status page raises a Critical warning for any range that allows it without authentication. **Remote → local** is inbound mail and must need no authentication. **Local → local** needs it on *Internet* so that nobody outside can forge mail from one of your addresses to another.

**The protection switches reach further than their names.** Clearing *Enable anti-spam* turns off every spam test, greylisting and the recipient tarpit for the range; clearing *Enable anti-virus* means its mail is never flagged for scanning. Since 6.3.4 SPF gives loopback no pass, so a content filter that re-injects mail should authenticate or use a range with anti-spam off.

**Require TLS for auth belongs to the range, not the port.** With it set, `AUTH` is not advertised on a cleartext connection from that range, on SMTP, POP3, IMAP and ManageSieve.

**A device that cannot sign in** gets a range of its own above *Internet*. For a scanner at 192.0.2.50 that sends from your domains to your own mailboxes only:

```bash
hmctl iprange create --set name=scanner --set lower=192.0.2.50 --set upper=192.0.2.50 \
  --set priority=20 --set allow_smtp=true --set allow_imap=false --set allow_pop3=false \
  --set deliver_local_to_local=true --set require_auth_local_to_local=false \
  --set deliver_local_to_remote=false --set deliver_remote_to_local=false \
  --set deliver_remote_to_remote=false --set spam_protection=true --set virus_protection=true
```

`hmctl iprange update <id>` and `PUT /api/v1/ipranges/{id}` (since 6.3.3) change any subset of the fields. The routes refuse a domain-restricted API key; a role needs `manage_settings`. **The Control Panel's Restore defaults** (`SecurityRanges.SetDefault()`) discards every range, your own and the auto-ban ones, and writes back the two shipped ones as the create scripts make them, without *Require TLS for auth*.

### Auto-ban, and why its ranges sit at priority 100

Auto-ban counts failed logons per **connecting address**; SMTP `AUTH`, POP3, IMAP, ManageSieve, the REST API and the web services listener's CardDAV, CalDAV and Autodiscover sign-ins feed one counter, but since 6.3.8 neither REST, for a failure from loopback (all of `127.0.0.0/8`, and `::1`), nor the web services listener, for one from loopback or an address in `WebServicesTrustedProxies`, counts it towards a ban of the address: an account's failed sign-in from there is counted against the name alone. Up to 6.3.7 an account's failed sign-in at REST from loopback was counted towards a ban of `127.0.0.1`, which could then be refused at the SMTP, POP3, IMAP and ManageSieve listeners; on 6.3.2 to 6.3.7 `AutoBanNeverBan` with `127.0.0.1, ::1` avoids it. **Behind a reverse proxy on the same machine** (the Linux package binds REST to `127.0.0.1`), the webmail's failed sign-ins are never auto-banned; account lockout, below, is what limits them there, and it is off until you set it.

At the limit auto-ban clears that address's counted failures, creates an expiring range named `Auto-ban: <user>` at **priority 100**, and disconnects; SMTP says `535 Authentication failed. Too many invalid logon attempts.` Priority 100, above both shipped ranges, is what makes a ban effective; `AutoBanNeverBan`, below, exempts an address.

| Setting (COM name) | Default | Trap |
|---|---|---|
| `AutoBanOnLogonFailure` | on | — |
| `MaxInvalidLogonAttempts` | 3 | **`0` disables auto-ban entirely**, whatever the switch says |
| `MaxInvalidLogonAttemptsWithin` | 30 minutes | Not a sliding window: how long a failure record survives, deleted by a pass every minute that runs only while auto-ban is on |
| `AutoBanMinutes` | 60 | **`0` disconnects the client but creates no range**, so nothing is banned |

Their REST keys include `auto_ban_on_logon_failure` and `max_invalid_logon_attempts`. The `office` profile (since 6.3.4) raises the limit to 5.

- **`AutoBanNeverBan`** (since 6.3.2): addresses and CIDR blocks whose failures are never counted; the per-connection disconnect still applies, and a bad entry is reported once as `HM6524`. Server status warns "Localhost is currently banned in the IP ranges." when a ban covers 127.0.0.1.
- **Control Panel sign-in over COM** is outside auto-ban and lockout, so guessing an administrator's mailbox name cannot lock them out of the tool.
- **Spam traps and the multi-recipient null-sender check** ban through the same ranges (`Auto-ban: spam trap <address>`, `Auto-ban: multi-recipient null sender <address>`): see [Allow and block lists](/topic/28249) and [the anti-spam stack](/topic/28248). Firewall bans (`AutoBanFirewall`, `AutoBanCommand`, fail2ban) are in [Reading the logs](/topic/28220).

**Releasing a banned address.** **Clear logon-failure list** (`POST /api/v1/settings/logon-failures/clear`, COM `Settings.ClearLogonFailureList()`) clears counted failures only, for every address at once; a ban stays until its range expires. To release one now:

1. Have the person correct the password in their client first: the counted failures were cleared when the ban was made, so a client still retrying the old one reaches the limit again as soon as the range is gone.
2. Find the range: the IP ranges page, the Deck's IP ranges view, `hmctl iprange list` or `GET /api/v1/ipranges`. Its name begins `Auto-ban:` and its priority is 100.
3. Delete it: on the page, `hmctl iprange delete <id>`, or `DELETE /api/v1/ipranges/<id>`. With `AutoBanFirewall` on, the firewall is reconciled on every range deletion, so its rule goes too.

Five error-log codes mean the control has quietly stopped working:

| Code | Meaning |
|---|---|
| `HM6114` | A failed logon could not be recorded, so no ban will trigger while this persists |
| `HM6099` | The auto-ban range could not be saved: the address has **not** been blocked |
| `HM6113` | Spent failures could not be cleared, so the address may be banned again as soon as its ban expires |
| `HM6112` | Expired IP ranges could not be removed, so an expired ban keeps blocking |
| `HM6115` | Expired failures could not be cleared, so occasional failures may add up to a ban |

### Account lockout, by name

A distributed attack never crosses any one address's threshold. Lockout counts the **name** being guessed at, across SMTP `AUTH`, POP3, IMAP, ManageSieve, REST and the webmail's sign-in. It is off until set; the `office` profile sets 10.

```ini
AccountLockoutThreshold=10       ; failed logons per username before a lockout. 0 = off
AccountLockoutWindowMinutes=30   ; the window they must fall inside
AccountLockoutMinutes=30         ; how long the lock lasts
```

- **It counts names, not accounts**, so a nonexistent name locks as a real one would, and reveals nothing.
- **A locked name is refused before the password is checked**, with the ordinary invalid-credentials reply; only its timing differs, deliberately.
- **A lockout refusal is not charged to the connecting address**, so an owner retrying from an office NAT does not get everyone behind it auto-banned.
- **Passkeys and single sign-on are not counted**, being no guesses.
- **To lift one early**: `POST /api/v1/accounts/{address}/unlock`, which a help desk scoped to the account's domain may call, COM `Application.UnlockAccount`, or **Unlock** on the Deck's Accounts row. A password reset clears it too.

### Tarpits and the submission rate limit

All **0, off, until set**; these values are a starting point.

```ini
LogonTarpitSeconds=2             ; per failure on this connection, capped at 30 s. 0 = off
SmtpTarpitCount=10               ; recipients an unauthenticated session may name before...
SmtpTarpitDelaySeconds=5         ; ...each further RCPT TO waits this long, capped at 30 s
MaxSubmissionsPerIPPerMinute=30  ; MAIL FROM commands per source IP per minute. 0 = off
```

- **The logon tarpit** (Auto-ban page) makes a failed logon's refusal wait `LogonTarpitSeconds` times the failures so far on that connection, on SMTP, POP3 and IMAP. **A correct password never waits.**
- **The recipient tarpit** (Anti-spam settings page; COM `AntiSpam.TarpitCount` and `AntiSpam.TarpitDelay`; REST `tarpit_count` and `tarpit_delay` on `/api/v1/settings/antispam`) spares authenticated sessions and ranges with anti-spam off.
- **`MaxSubmissionsPerIPPerMinute` counts every `MAIL FROM`, authenticated or not**, and refuses the excess with `421 Too many messages from your IP address`, which contains a compromised account. The `office` profile sets 60; `gateway` keeps 0, since all inbound mail comes from the gateway's few addresses. Since 6.3.4 a save restarts its one-minute window.

Behind a load balancer, give the SMTP listener `SMTPProxyProtocolEnabled` with `SMTPProxyProtocolTrustedIPs` (or `XCLIENT`), or auto-ban, the rate limit and the ranges all reason about the proxy's address: see [Behind a gateway or reverse proxy](/topic/28240).

### Per-account sending limits

The brake on a compromised account, counted against the **authenticated user name** (never `MAIL FROM`) over a rolling period. The server level stays in the file:

```ini
[SendingLimits]
MaxMessagesPerAccountPerPeriod=500
MaxRecipientsPerAccountPerPeriod=2000
PeriodHours=24                   ; clamped to 1-168
StateSaveIntervalSeconds=10      ; clamped to 1-3600

[SendingLimitsOverrides]
newsletter@yourcompany.com=5000:50000
ceo@yourcompany.com=0:0
```

Both limits default to 0, no limit; recipients are the stricter measure. An override replaces the global pair for that address, `0:0` exempts it, and an optional third field sets its period in hours; a malformed line is ignored with a log entry and the global limit applies. On Windows edit `C:\Program Files\hMailServer\Bin\hMailServer.INI` with an elevated editor, or use the Control Panel's **Maintenance → Server limits & expert settings** on the server itself; on Linux, `sudoedit /etc/hmailserver/hMailServer.ini`. They are not in the settings store, so no environment variable or setting profile writes them.

**What the sender sees**: `452 4.7.0 Sending limit for this account has been reached. Please try again later.` at `MAIL FROM`, or `452 4.5.3 Recipient sending limit for this account has been reached. Please try again later.` at `RCPT TO`. The session stays open, the refusal spends no budget, and the application log, not the error log, says `SendingLimit refused submission`. Counters survive a restart in `hmailserver_sendinglimits.dat` in the data directory. **It fails open**: an unreadable file, a limiter exception or a full table of tracked accounts (error 5813) lets the message through.

**Since 6.3.4 there are three levels.** A domain and an account may hold `sending_max_messages` and `sending_max_recipients`, which **tighten** the level above and never loosen it; an address's override line is its server level. Set them on the **Levels** tab of the domain and account dialogs, in the Deck's editors, with `PUT /api/v1/accounts/{address}`, or `hmctl account set <address> sending_max_messages 100` (`inherit` returns to the level above); they apply at once. Also since 6.3.4 the webmail's send and the send API consume the same quota, answering `429`; a scheduled draft is not counted when it goes.

### Who may send as whom

`SmtpAuthenticatedSenderCheck` (Control Panel **Connections & protocols → Protocols**, SMTP tab) came in 6.2.25 and is off by default, since an installation may depend on what off allows: any account sending as anyone. The `office` and `gateway` profiles set it to 1. Turned on, it applies to every authenticated session, whose `MAIL FROM` must then be:

| Kind | Given by |
|---|---|
| The account's own address | always |
| An alias resolving to it, up to five hops | the administrator |
| A mailbox whose owner granted the **post (`p`) right on their INBOX** | that owner, with any IMAP client's `SETACL` |
| An address elsewhere proved by a code mailed to it (since 6.3.4) | the person, in the webmail's *Settings, Other accounts, Send mail as* |
| A masked address the account made, while it is on (since 6.3.4) | the person, in the webmail's *Settings, Masked addresses* |

Anything else is refused `550 5.7.1` before the message is accepted. The webmail's From picker lists exactly these, so what it offers is what the server takes. The null sender is always allowed; unauthenticated sessions are unaffected. **The post right counts only while IMAP ACL enforcement is on** (`enableimapacl`, on by default). Before turning the check on, grant `p` to every delegate who sends as a shared mailbox. Mail sent as a proved outside address is not aligned with that address's domain, so a receiver honouring its DMARC policy may quarantine or refuse it.

### How passwords are stored

In the Control Panel, **Access & abuse protection → Authentication**, card **Password storage**. Schemes: 0 none, 1 Blowfish, 2 MD5, 3 SHA-256, 4 PBKDF2-HMAC-SHA256 (the default), 5 Argon2id, 6 DPAPI (stored secrets only), 7 scrypt.

```ini
PreferredHashAlgorithm=4         ; 3, 4, 5 or 7. Anything else is refused (HM5528) and read as 4
MinimumAcceptedHashAlgorithm=0   ; refuse a logon whose stored hash is weaker. 0 = off
PasswordPepper=                  ; a server-wide secret mixed into Argon2id and scrypt hashes
PasswordHashIterations=0         ; PBKDF2. 0 = 210,000. Range 10,000 to 10,000,000
PasswordHashMemoryKB=0           ; Argon2id. 0 = 19,456 KiB. Range 4,096 to 1,048,576
PasswordHashTimeCost=0           ; Argon2id passes. 0 = 2. Range 1 to 20
```

- **Hashes upgrade at a successful logon, only upward.** Raising the scheme or a work factor re-derives each hash when its owner next signs in; lowering either affects new hashes only.
- **`MinimumAcceptedHashAlgorithm` set too high is a lockout.** The refusal follows a correct comparison and the upgrade needs a successful logon, so an account below the floor never climbs out: its password must be reset. Raise the preference first, let accounts sign in, then set the floor. Argon2id and scrypt are peers, so 5 accepts either.
- **A work factor out of range** is reported as `HM5561` and read as 0; `HM5607` means Argon2id was asked for on a build whose OpenSSL has none, and another scheme is used. Argon2id allocates `PasswordHashMemoryKB` on a connection thread at every logon.
- **`PasswordPepper` must be set before accounts exist**: changing it invalidates every Argon2id and scrypt password. PBKDF2 is not peppered, so it stays usable for SCRAM. Since 6.3.4 it lives in `hMailServer.ini` only and no backup carries it, so **keep a copy of the value with the backups**: a database or archive restored onto a machine whose file has no pepper, or a different one, refuses every Argon2id and scrypt password, and a warm standby needs the same value in its own file. Where the service cannot write the file (a new Windows installation running as `NT SERVICE\hMailServer`, or a Linux package installation), COM and REST refuse it: set it with an elevated editor (`sudoedit` on Linux) and restart the service.

### The password policy

All off until set, applied **where a password is chosen**, never at logon; on Windows under **Access & abuse protection → Administrative access**, Password tab.

```ini
PasswordPolicyMinimumLength=12
PasswordPolicyRequireMixedCase=1
PasswordPolicyRequireDigit=1
PasswordPolicyRequireNonAlphanumeric=1
PasswordPolicyRejectCommon=1        ; refuse passwords from a built-in common list
PasswordPolicyHistoryCount=5        ; refuse the last N passwords
PasswordPolicyMaximumAgeDays=0      ; 0 = passwords never expire
```

The `office` profile sets a minimum of 10 and the common list. **Expiry needs care**: IMAP, POP3 and SMTP cannot change a password and `/portal` refuses an expired one, so an administrator renews it, or its owner through an app password, which still signs in to `/portal`. Active Directory accounts are exempt. The breach check is in [Hardening a public mail server](/topic/28241); the rest of sign-in is in [Signing in](/topic/28253).

### What it does not do

- None of it spam-tests your own users: an authenticated session never is.
- A setting profile never writes an IP range.

### Where to read more

- Wiki: [Security Hardening](https://gitlab.com/hmailserver/hmailserver/-/wikis/Security-Hardening) sections 17.1, 17.2, 17.5, 17.7 and 17.9; [Settings Reference](https://gitlab.com/hmailserver/hmailserver/-/wikis/Settings-Reference) sections 9.1, 9.9 and 10; [Stopping Spam](https://gitlab.com/hmailserver/hmailserver/-/wikis/Stopping-Spam) section 10.1; [Troubleshooting](https://gitlab.com/hmailserver/hmailserver/-/wikis/Troubleshooting) sections 19.3 and 19.7.
- Documents: [SettingsApply.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingsApply.md), [SettingLevels.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SettingLevels.md), [SendAs.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/SendAs.md), [Profiles.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Profiles.md), [Roles.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/Roles.md), [ServiceAccount.md](https://gitlab.com/hmailserver/hmailserver/-/blob/v6.3.4/hmailserver/docs/ServiceAccount.md).
- Public documentation: [SecurityRange and SecurityRanges](https://www.progressiverobot.com/hmailserver-documentation/#securityrange-and-securityranges), for the COM names of the range flags.
- On this forum: [Being trusted by the servers you send to](/topic/28188), [The Control Deck](/topic/28192), [Upgrading to 6.3.4](/topic/28193), [hMailServer on Linux](/topic/28189).
