Better-IP-Filter is a lightweight and fast IP whitelist plugin for Minecraft Paper servers.
It performs early IP validation during the login process and blocks connections from non-whitelisted IP addresses with minimal performance impact.
- IP whitelist filtering on player join
- Uses
AsyncPlayerPreLoginEvent(early, efficient check) - Toggleable filtering without server restart
- Extremely lightweight (O(1) lookups)
- No external dependencies
- IPv4 validation (exact, CIDR, and ranges)
- Persistent storage (
ips.yml) - Proxy trusted-forwarded IP gate (no header parsing)
- Optional rate limiting and failsafe behavior
- Optional webhook notifications
- Fully compatible with LuckPerms (Bukkit permissions)
- Java: 21 or newer
- Server: Paper 1.21 - 1.21.11, 26.1 - 26.1.2
- Build tool: Maven (only if building from source)
- Download the compiled
Better-IP-Filter.jar - Place it into your serverβs
plugins/directory - Start the server once to generate configuration files
- Edit
config.ymlif needed - Restart the server
The plugin configuration is located in config.yml.
enabled: true
messages:
prefix: "&7[&bBetter-IP-Filter&7] &r"
notAllowed: "&cYour IP address is not allowed on this server."
enabled: "&aIP filtering enabled."
disabled: "&eIP filtering disabled."
added: "&aAdded IP: &f{ip}"
alreadyExists: "&eIP already exists: &f{ip}"
removed: "&aRemoved IP: &f{ip}"
notFound: "&cIP not found: &f{ip}"
failedUpdate: "&cFailed to update whitelist."
storeUnavailable: "&cWhitelist storage unavailable."
invalidIp: "&cInvalid IP address: &f{ip}"
listHeader: "&bWhitelisted entries &7({count})&b:"
noPermission: "&cYou do not have permission to do that."
reloaded: "&aConfiguration reloaded."
statusHeader: "&bBetter-IP-Filter status:"
proxyNotTrusted: "&cConnection denied: proxy is not trusted."
proxy:
mode: "DIRECT" # DIRECT | PROXY_GATE
trusted-forwarded-ips: []
ratelimit:
enabled: true
window-seconds: 10
max-attempts: 5
message: "&cToo many connection attempts. Try again later."
failsafe:
mode: "DENY_ALL" # DENY_ALL | ALLOW_ALL
message: "&cWhitelist unavailable. Try again later."
logging:
denied: true
denied-to-file: true
file-name: "denied.log"
async-queue-size: 8192
async-batch-size: 64
async-flush-interval-ms: 1000
async-drop-log-interval-seconds: 10
webhook:
enabled: false
url: ""
allow-local-addresses: false
on-denied: true
on-ratelimit: true
on-failsafe: true
timeout-ms: 3000
max-per-second: 5
max-queue-size: 1000enabled- enables or disables IP filtering globallymessages- fully customizable plugin messages (supports color codes)proxy.mode- connection semantics: DIRECT or PROXY_GATEproxy.trusted-forwarded-ips- list of trusted proxy IPs used as a gateratelimit- connection attempt throttlingfailsafe- what to do when storage or IP parsing failslogging- audit logging for denied connectionswebhook- optional JSON notifications for denies
Security defaults:
failsafe.mode: "DENY_ALL"rejects joins when whitelist storage or IP parsing is unavailable.webhook.allow-local-addresses: falseblocks literal localhost/private webhook targets by default.- Denied logs and webhook payloads contain player names and IP addresses; keep them private.
Whitelist entries accept only IPv4 values in these formats:
- Exact IP:
203.0.113.10 - CIDR block:
203.0.113.0/24 - Range:
203.0.113.10-203.0.113.50
Entries are normalized when saved to ips.yml.
| Command | Description |
|---|---|
/ipf add <ip> |
Add an IP to the whitelist |
/ipf remove <ip> |
Remove an IP from the whitelist |
/ipf list |
Show all whitelisted IPs |
/ipf status |
Show plugin diagnostics |
/ipf reload |
Reload config and whitelist |
/ipf on |
Enable IP filtering |
/ipf off |
Disable IP filtering |
| Permission | Description | Default |
|---|---|---|
betteripfilter.admin |
Full access | OP |
betteripfilter.add |
Add IPs | OP |
betteripfilter.remove |
Remove IPs | OP |
betteripfilter.list |
View whitelist | OP |
betteripfilter.status |
View status | OP |
betteripfilter.reload |
Reload plugin data | OP |
betteripfilter.toggle |
Enable/disable filter | OP |
The plugin uses standard Bukkit permissions and works seamlessly with LuckPerms.
- The plugin listens to
AsyncPlayerPreLoginEvent - The playerβs IP address is checked before they fully join the server
- Whitelisted IPs are stored in memory (
HashSet) for O(1) lookup - If the IP is not allowed, the connection is denied immediately
- No permission bypass is used by design to keep checks fast and secure
- In
DIRECT, whitelist checks run against the connection IP seen by Paper. - In
PROXY_GATE, the connection IP must be inproxy.trusted-forwarded-ipsbefore whitelist/rate checks continue. - For Velocity modern forwarding, security must primarily rely on the forwarding secret configured in both Paper and Velocity. The plugin's proxy gate is an additional connection-level IP gate and does not parse forwarded headers.
- Rate limiting throttles rapid login attempts based on source IP
- Failsafe mode controls what happens when storage or IP parsing is unavailable
- Denied log entries include IP addresses (privacy note: treat logs as sensitive)
- No scheduled tasks
- No reflection or NMS usage
- Constant-time IP lookups
- Thread-safe handling for async login events
- Negligible memory footprint
Designed to run on production servers with zero noticeable overhead.
After first launch:
plugins/Better-IP-Filter/
βββ Better-IP-Filter.jar
βββ config.yml
βββ ips.yml
mvn clean packageThe compiled JAR will be available in:
target/Better-IP-Filter-1.4.3.jar
- β Paper/Spigot/etc
- β Minecraft 1.21 - 1.21.11
- β Minecraft 26.1 - 26.1.2
This project is licensed under the MIT License. You are free to use, modify, and distribute it in both private and commercial projects.
Better-IP-Filter β simple, fast, and secure IP filtering for modern Paper servers.
