diff --git a/cmd/policy/main.go b/cmd/policy/main.go
index 7c0364b6915286a9aee0ca859dc0e3e3d32e3e1e..6a898fe85bdb67633840de501214d02533d7b10a 100644
--- a/cmd/policy/main.go
+++ b/cmd/policy/main.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/jpillora/ipfilter"
 	"github.com/kelseyhightower/envconfig"
 	"github.com/open-policy-agent/opa/rego"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -183,6 +184,17 @@ func main() {
 	// Apply middlewares on the servers
 	policyServer.Evaluate = header.Middleware()(policyServer.Evaluate)
 
+	// Apply IP filter middleware if enabled
+	if cfg.IPFilter.Enabled {
+		m := ipfilter.New(ipfilter.Options{
+			AllowedIPs:     cfg.IPFilter.AllowedIPs,
+			BlockByDefault: true,
+			Logger:         zap.NewStdLog(logger),
+		})
+
+		policyServer.Use(m.Wrap)
+	}
+
 	// Apply Authentication middleware if enabled
 	if cfg.Auth.Enabled {
 		m, err := auth.NewMiddleware(cfg.Auth.JwkURL, cfg.Auth.RefreshInterval, httpClient)
diff --git a/go.mod b/go.mod
index 687b40158db2c5f2c7cc575a4d92482c49895787..038b820f468f016ce77c0ba46ccca83d6be03f64 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.19
 
 require (
 	github.com/google/uuid v1.3.0
+	github.com/jpillora/ipfilter v1.2.8
 	github.com/kelseyhightower/envconfig v1.4.0
 	github.com/open-policy-agent/opa v0.44.0
 	github.com/prometheus/client_golang v1.13.0
@@ -45,6 +46,7 @@ require (
 	github.com/manveru/faker v0.0.0-20171103152722-9fbc68a78c4d // indirect
 	github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
 	github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
+	github.com/phuslu/iploc v1.0.20220830 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/prometheus/client_model v0.2.0 // indirect
@@ -54,6 +56,7 @@ require (
 	github.com/sergi/go-diff v1.2.0 // indirect
 	github.com/smartystreets/assertions v1.13.0 // indirect
 	github.com/tchap/go-patricia/v2 v2.3.1 // indirect
+	github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/scram v1.1.1 // indirect
 	github.com/xdg-go/stringprep v1.0.3 // indirect
diff --git a/go.sum b/go.sum
index 8bdd0c3cca2afbb266e8cadca7716dc0139eedea..5dd78ecccaa4a21edd20794b634b557065552c03 100644
--- a/go.sum
+++ b/go.sum
@@ -178,6 +178,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/jpillora/ipfilter v1.2.8 h1:1H0qabCORKpA6lCTSr6dkrpUiAeqQTRa+tu9pMtcDn8=
+github.com/jpillora/ipfilter v1.2.8/go.mod h1:wZ2Aj18JsM61oMXtb4Er99cOjuuuCFyoBYljjQW/ytU=
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -231,6 +233,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/open-policy-agent/opa v0.44.0 h1:sEZthsrWBqIN+ShTMJ0Hcz6a3GkYsY4FaB2S/ou2hZk=
 github.com/open-policy-agent/opa v0.44.0/go.mod h1:YpJaFIk5pq89n/k72c1lVvfvR5uopdJft2tMg1CW/yU=
+github.com/phuslu/iploc v1.0.20220830 h1:rH+Hc0ylIL2CNnHbfTYkYCOXvQu9gEAgih232YED1yg=
+github.com/phuslu/iploc v1.0.20220830/go.mod h1:gsgExGWldwv1AEzZm+Ki9/vGfyjkL33pbSr9HGpt2Xg=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -288,6 +292,8 @@ github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BG
 github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
 github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
+github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
 github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
diff --git a/internal/config/config.go b/internal/config/config.go
index 5073ffd9bb0052349642b808e92b78454095b700..101354c8c24afa955baed98be5f97597993b0f12 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -14,6 +14,7 @@ type Config struct {
 	OAuth       oauthConfig
 	Refresher   refresherConfig
 	Auth        authConfig
+	IPFilter    ipFilterConfig
 
 	LogLevel string `envconfig:"LOG_LEVEL" default:"INFO"`
 }
@@ -73,3 +74,8 @@ type authConfig struct {
 	JwkURL          string        `envconfig:"AUTH_JWK_URL"`
 	RefreshInterval time.Duration `envconfig:"AUTH_REFRESH_INTERVAL" default:"1h"`
 }
+
+type ipFilterConfig struct {
+	Enabled    bool     `envconfig:"IP_FILTER_ENABLE" default:"false"`
+	AllowedIPs []string `envconfig:"IP_FILTER_ALLOWED_IPS"`
+}
diff --git a/vendor/github.com/jpillora/ipfilter/LICENSE.md b/vendor/github.com/jpillora/ipfilter/LICENSE.md
new file mode 100644
index 0000000000000000000000000000000000000000..98ab1d587f9d8aba2b284cc177472e21e828d1bf
Binary files /dev/null and b/vendor/github.com/jpillora/ipfilter/LICENSE.md differ
diff --git a/vendor/github.com/jpillora/ipfilter/README.md b/vendor/github.com/jpillora/ipfilter/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7a8e8d11f515a651f103d4996de84172f586c9a5
Binary files /dev/null and b/vendor/github.com/jpillora/ipfilter/README.md differ
diff --git a/vendor/github.com/jpillora/ipfilter/ipfilter.go b/vendor/github.com/jpillora/ipfilter/ipfilter.go
new file mode 100644
index 0000000000000000000000000000000000000000..72bbc77e0300efc1b6bc7613f5adbdd44029f8c2
Binary files /dev/null and b/vendor/github.com/jpillora/ipfilter/ipfilter.go differ
diff --git a/vendor/github.com/phuslu/iploc/LICENSE b/vendor/github.com/phuslu/iploc/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..f31dd8a45363ceb08687d7f26da97fe1ca3a1a0d
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/LICENSE differ
diff --git a/vendor/github.com/phuslu/iploc/README.md b/vendor/github.com/phuslu/iploc/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0750b3b2311c084e5b2dfe82dc4bdf233f7be087
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/README.md differ
diff --git a/vendor/github.com/phuslu/iploc/iploc.go b/vendor/github.com/phuslu/iploc/iploc.go
new file mode 100644
index 0000000000000000000000000000000000000000..b182065abc2c824db3beaf22f2d41b04b06dd6fd
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/iploc.go differ
diff --git a/vendor/github.com/phuslu/iploc/iploc_be.go b/vendor/github.com/phuslu/iploc/iploc_be.go
new file mode 100644
index 0000000000000000000000000000000000000000..f69078ad33b8c34477d09e2ab93a77090da20328
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/iploc_be.go differ
diff --git a/vendor/github.com/phuslu/iploc/iploc_le.go b/vendor/github.com/phuslu/iploc/iploc_le.go
new file mode 100644
index 0000000000000000000000000000000000000000..e5094e2339273f81e04c3bc0a7d6656a68c8f7a8
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/iploc_le.go differ
diff --git a/vendor/github.com/phuslu/iploc/ipv4.txt b/vendor/github.com/phuslu/iploc/ipv4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b56add1224813efa47ad380bc921418e4ba1df17
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/ipv4.txt differ
diff --git a/vendor/github.com/phuslu/iploc/ipv4be.bin b/vendor/github.com/phuslu/iploc/ipv4be.bin
new file mode 100644
index 0000000000000000000000000000000000000000..675dec631140cac8a09314fdaf35dbcd051a0a8f
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/ipv4be.bin differ
diff --git a/vendor/github.com/phuslu/iploc/ipv4le.bin b/vendor/github.com/phuslu/iploc/ipv4le.bin
new file mode 100644
index 0000000000000000000000000000000000000000..8bdf5447d9e888ce369600d5047d7e8914da3269
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/ipv4le.bin differ
diff --git a/vendor/github.com/phuslu/iploc/ipv6.txt b/vendor/github.com/phuslu/iploc/ipv6.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f5f68b15736ee92f04b05683b5300326dd9f1b11
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/ipv6.txt differ
diff --git a/vendor/github.com/phuslu/iploc/ipv6be.gz b/vendor/github.com/phuslu/iploc/ipv6be.gz
new file mode 100644
index 0000000000000000000000000000000000000000..0a6f9c5cb38f00d7c3c1e73eaa1e0342e02c47a7
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/ipv6be.gz differ
diff --git a/vendor/github.com/phuslu/iploc/ipv6le.gz b/vendor/github.com/phuslu/iploc/ipv6le.gz
new file mode 100644
index 0000000000000000000000000000000000000000..d3793635328e586eb3016cfab784f0ee979993f6
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/ipv6le.gz differ
diff --git a/vendor/github.com/phuslu/iploc/update-db.py b/vendor/github.com/phuslu/iploc/update-db.py
new file mode 100644
index 0000000000000000000000000000000000000000..99de2854361f43c80a7ae3a1926a0bd7cd4d40d4
Binary files /dev/null and b/vendor/github.com/phuslu/iploc/update-db.py differ
diff --git a/vendor/github.com/tomasen/realip/.travis.yml b/vendor/github.com/tomasen/realip/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fdfbf87553e8adffca7a1dfd48f3178752e2e546
Binary files /dev/null and b/vendor/github.com/tomasen/realip/.travis.yml differ
diff --git a/vendor/github.com/tomasen/realip/LICENSE b/vendor/github.com/tomasen/realip/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..977c3511a094ede70135905ebb2911e152e5b4b9
Binary files /dev/null and b/vendor/github.com/tomasen/realip/LICENSE differ
diff --git a/vendor/github.com/tomasen/realip/README.md b/vendor/github.com/tomasen/realip/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a7bb120374133200a84bc2b9531eb66f3ce3c0d8
Binary files /dev/null and b/vendor/github.com/tomasen/realip/README.md differ
diff --git a/vendor/github.com/tomasen/realip/realip.go b/vendor/github.com/tomasen/realip/realip.go
new file mode 100644
index 0000000000000000000000000000000000000000..e2803a2bc147b1b23ad700d941424951502c08d6
Binary files /dev/null and b/vendor/github.com/tomasen/realip/realip.go differ
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9d6b48019cc9128ec8a8c4f4aa0f67d1afd0f799..7b38227c30ccdffe91f8031cf87fe29c654ba75b 100644
Binary files a/vendor/modules.txt and b/vendor/modules.txt differ