2017-04-30 09:22:07 +00:00
|
|
|
package middlewares
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/containous/traefik/log"
|
2018-01-10 16:48:04 +00:00
|
|
|
"github.com/containous/traefik/middlewares/tracing"
|
2017-10-10 12:50:03 +00:00
|
|
|
"github.com/containous/traefik/whitelist"
|
2017-05-26 15:03:14 +00:00
|
|
|
"github.com/pkg/errors"
|
2017-07-19 10:02:51 +00:00
|
|
|
"github.com/urfave/negroni"
|
2017-04-30 09:22:07 +00:00
|
|
|
)
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
// IPWhiteLister is a middleware that provides Checks of the Requesting IP against a set of Whitelists
|
|
|
|
type IPWhiteLister struct {
|
|
|
|
handler negroni.Handler
|
|
|
|
whiteLister *whitelist.IP
|
2017-04-30 09:22:07 +00:00
|
|
|
}
|
|
|
|
|
2018-03-23 16:40:04 +00:00
|
|
|
// NewIPWhiteLister builds a new IPWhiteLister given a list of CIDR-Strings to whitelist
|
|
|
|
func NewIPWhiteLister(whiteList []string, useXForwardedFor bool) (*IPWhiteLister, error) {
|
|
|
|
if len(whiteList) == 0 {
|
|
|
|
return nil, errors.New("no white list provided")
|
2017-04-30 09:22:07 +00:00
|
|
|
}
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
whiteLister := IPWhiteLister{}
|
2017-07-10 12:58:31 +00:00
|
|
|
|
2018-03-23 16:40:04 +00:00
|
|
|
ip, err := whitelist.NewIP(whiteList, false, useXForwardedFor)
|
2017-10-10 12:50:03 +00:00
|
|
|
if err != nil {
|
2018-03-23 16:40:04 +00:00
|
|
|
return nil, fmt.Errorf("parsing CIDR whitelist %s: %v", whiteList, err)
|
2017-04-30 09:22:07 +00:00
|
|
|
}
|
2017-10-10 12:50:03 +00:00
|
|
|
whiteLister.whiteLister = ip
|
2017-04-30 09:22:07 +00:00
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
whiteLister.handler = negroni.HandlerFunc(whiteLister.handle)
|
2018-03-23 16:40:04 +00:00
|
|
|
log.Debugf("configured %u IP white list: %s", len(whiteList), whiteList)
|
2017-04-30 09:22:07 +00:00
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
return &whiteLister, nil
|
2017-04-30 09:22:07 +00:00
|
|
|
}
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
func (wl *IPWhiteLister) handle(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
2018-03-23 16:40:04 +00:00
|
|
|
allowed, ip, err := wl.whiteLister.IsAuthorized(r)
|
2017-10-10 12:50:03 +00:00
|
|
|
if err != nil {
|
2018-03-23 16:40:04 +00:00
|
|
|
tracing.SetErrorAndDebugLog(r, "request %+v matched none of the white list - rejecting", r)
|
2017-10-10 12:50:03 +00:00
|
|
|
reject(w)
|
|
|
|
return
|
2017-04-30 09:22:07 +00:00
|
|
|
}
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
if allowed {
|
2018-03-23 16:40:04 +00:00
|
|
|
tracing.SetErrorAndDebugLog(r, "request %+v matched white list %s - passing", r, wl.whiteLister)
|
2017-10-10 12:50:03 +00:00
|
|
|
next.ServeHTTP(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-03-23 16:40:04 +00:00
|
|
|
tracing.SetErrorAndDebugLog(r, "source-IP %s matched none of the white list - rejecting", ip)
|
2017-04-30 09:22:07 +00:00
|
|
|
reject(w)
|
|
|
|
}
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
func (wl *IPWhiteLister) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
|
|
|
wl.handler.ServeHTTP(rw, r, next)
|
|
|
|
}
|
|
|
|
|
2017-04-30 09:22:07 +00:00
|
|
|
func reject(w http.ResponseWriter) {
|
|
|
|
statusCode := http.StatusForbidden
|
|
|
|
|
|
|
|
w.WriteHeader(statusCode)
|
|
|
|
w.Write([]byte(http.StatusText(statusCode)))
|
|
|
|
}
|