IpFilter
in package
CIDR-based IP allowlist for incoming webhook requests.
Mirrors upstream aiogram.webhook.security.IPFilter (aiogram/webhook/security.py).
Perf-tuned divergence from upstream's hosts-set approach
The Python upstream materialises every host address in each added network into
a set[IPv4Address] and performs O(1) set-membership checks. For Telegram's
default ranges (/20 + /22 ≈ 5 K addresses) this is acceptable in Python but
wastes memory for no gain in PHP where the allowed network list is tiny (n=2
for the default config).
This implementation stores each allowed range as a (networkLong, prefix)
tuple and performs an O(n) bitwise-mask check on each check() call:
($ipLong & $mask) === $networkLong
With n=2 the difference is immeasurable in practice, and the implementation avoids allocating a ~5 K-entry array.
Host-address semantics (upstream parity)
check() rejects network and broadcast addresses for prefix lengths 1–30,
matching Python's IPv4Network.hosts() which excludes them. For /31 and /32
all addresses in the range are usable hosts (RFC 3021 for /31). For /0 the
network address (0.0.0.0) and broadcast address (255.255.255.255) are
excluded, matching the same rule applied consistently across all non-/31/32
prefix lengths.
Table of Contents
Constants
- DEFAULT_TELEGRAM_NETWORKS : array<string|int, mixed> = ['149.154.160.0/20', '91.108.4.0/22']
- Telegram's documented IPv4 ranges from which webhook requests originate.
Properties
- $networks : array<int, array{network: int, prefix: int}>
- Stored as a list of [networkLong, prefix] pairs.
Methods
- __construct() : mixed
- allow() : void
- Add one or more IPv4 addresses or CIDR ranges to the allowlist.
- check() : bool
- Return `true` when `$ip` is a usable host address in any allowed network.
- default() : self
- Return a new `IpFilter` pre-loaded with Telegram's documented IP ranges.
- addCidr() : void
- addEntry() : void
- Parse a single CIDR or bare-IP string and append to `$this->networks`.
- addSingleIp() : void
Constants
DEFAULT_TELEGRAM_NETWORKS
Telegram's documented IPv4 ranges from which webhook requests originate.
public
array<string|int, mixed>
DEFAULT_TELEGRAM_NETWORKS
= ['149.154.160.0/20', '91.108.4.0/22']
Source: https://core.telegram.org/bots/webhooks#the-telegram-bot-api-server
Properties
$networks
Stored as a list of [networkLong, prefix] pairs.
private
array<int, array{network: int, prefix: int}>
$networks
= []
networkLong is the 32-bit integer representation of the network address
(result of ip2long()), prefix is the CIDR prefix length (0–32).
Methods
__construct()
public
__construct([array<int, string> $ips = [] ]) : mixed
Parameters
- $ips : array<int, string> = []
-
Zero or more CIDR ranges (
'1.2.3.0/24') or individual IPv4 addresses ('1.2.3.4'). Each entry is forwarded to allow().
allow()
Add one or more IPv4 addresses or CIDR ranges to the allowlist.
public
allow(string ...$ips) : void
Parameters
- $ips : string
-
Each argument must be an IPv4 address (
'1.2.3.4') or a CIDR notation string ('1.2.3.0/24').
Tags
check()
Return `true` when `$ip` is a usable host address in any allowed network.
public
check(string $ip) : bool
Matches upstream IPv4Network.hosts() semantics: for prefix lengths 1–30
the network address (lowest) and broadcast address (highest) are excluded.
For /31 and /32 all addresses in the range are usable (RFC 3021 for /31;
/32 is a single host by definition). For /0 the network address
(0.0.0.0) and broadcast address (255.255.255.255) are also excluded.
Returns false without throwing when $ip is syntactically invalid or
IPv6-formatted, mirroring the upstream behaviour where an address that
cannot be compared simply does not match.
Parameters
- $ip : string
-
An IPv4 address string to test (e.g.
'1.2.3.4').
Return values
booldefault()
Return a new `IpFilter` pre-loaded with Telegram's documented IP ranges.
public
static default() : self
Equivalent to new self(self::DEFAULT_TELEGRAM_NETWORKS).
Return values
selfaddCidr()
private
addCidr(string $cidr) : void
Parameters
- $cidr : string
Tags
addEntry()
Parse a single CIDR or bare-IP string and append to `$this->networks`.
private
addEntry(string $entry) : void
Parameters
- $entry : string
Tags
addSingleIp()
private
addSingleIp(string $ip) : void
Parameters
- $ip : string