forked from TykTechnologies/tyk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: api blacklisting middleware
refs: TykTechnologies#1545 This PR adds IP Blacklisting Middleware. It works in same way as IP Whitelisting.
- Loading branch information
Showing
8 changed files
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"net" | ||
"net/http" | ||
) | ||
|
||
// IPBlackListMiddleware lets you define a list of IPs to block from upstream | ||
type IPBlackListMiddleware struct { | ||
BaseMiddleware | ||
} | ||
|
||
func (i *IPBlackListMiddleware) Name() string { | ||
return "IPBlackListMiddleware" | ||
} | ||
|
||
func (i *IPBlackListMiddleware) EnabledForSpec() bool { | ||
return i.Spec.EnableIpBlacklisting && len(i.Spec.BlacklistedIPs) > 0 | ||
} | ||
|
||
// ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail | ||
func (i *IPBlackListMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) { | ||
remoteIP := net.ParseIP(requestIP(r)) | ||
|
||
// Enabled, check incoming IP address | ||
for _, ip := range i.Spec.BlacklistedIPs { | ||
// Might be CIDR, try this one first then fallback to IP parsing later | ||
blockedIP, blockedNet, err := net.ParseCIDR(ip) | ||
if err != nil { | ||
blockedIP = net.ParseIP(ip) | ||
} | ||
|
||
// Check CIDR if possible | ||
if blockedNet != nil && blockedNet.Contains(remoteIP) { | ||
|
||
return i.handleError(r, remoteIP.String()) | ||
} | ||
|
||
// We parse the IP to manage IPv4 and IPv6 easily | ||
if blockedIP.Equal(remoteIP) { | ||
|
||
return i.handleError(r, remoteIP.String()) | ||
} | ||
} | ||
|
||
return nil, http.StatusOK | ||
} | ||
|
||
func (i *IPBlackListMiddleware) handleError(r *http.Request, blacklistedIP string) (error, int) { | ||
|
||
// Fire Authfailed Event | ||
AuthFailed(i, r, blacklistedIP) | ||
// Report in health check | ||
reportHealthValue(i.Spec, KeyFailure, "-1") | ||
return errors.New("access from this IP has been disallowed"), http.StatusForbidden | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package main | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
) | ||
|
||
func TestIPBlacklistMiddleware(t *testing.T) { | ||
spec := buildAPI(func(spec *APISpec) { | ||
spec.EnableIpBlacklisting = true | ||
spec.BlacklistedIPs = []string{"127.0.0.1", "127.0.0.1/24"} | ||
})[0] | ||
|
||
for ti, tc := range []struct { | ||
remote, forwarded string | ||
wantCode int | ||
}{ | ||
{"127.0.0.1:80", "", http.StatusForbidden}, // remote exact match | ||
{"127.0.0.2:80", "", http.StatusForbidden}, // remote CIDR match | ||
{"10.0.0.1:80", "", http.StatusOK}, // no match | ||
{"10.0.0.1:80", "127.0.0.1", http.StatusForbidden}, // forwarded exact match | ||
{"10.0.0.1:80", "127.0.0.2", http.StatusForbidden}, // forwarded CIDR match | ||
} { | ||
rec := httptest.NewRecorder() | ||
req := testReq(t, "GET", "/", nil) | ||
req.RemoteAddr = tc.remote | ||
if tc.forwarded != "" { | ||
req.Header.Set("X-Forwarded-For", tc.forwarded) | ||
} | ||
|
||
mw := &IPBlackListMiddleware{} | ||
mw.Spec = spec | ||
_, code := mw.ProcessRequest(rec, req, nil) | ||
|
||
if code != tc.wantCode { | ||
t.Errorf("[%d] Response code %d should be %d\n%q %q", ti, | ||
code, tc.wantCode, tc.remote, tc.forwarded) | ||
} | ||
} | ||
} |