2017-04-30 11:22:07 +02:00
package middlewares
import (
"fmt"
"net"
"net/http"
"github.com/containous/traefik/log"
2017-10-10 14:50:03 +02:00
"github.com/containous/traefik/whitelist"
2017-05-26 17:03:14 +02:00
"github.com/pkg/errors"
2017-07-19 12:02:51 +02:00
"github.com/urfave/negroni"
2017-04-30 11:22:07 +02:00
)
2017-10-10 14:50:03 +02: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 11:22:07 +02:00
}
2017-10-10 14:50:03 +02:00
// NewIPWhitelister builds a new IPWhiteLister given a list of CIDR-Strings to whitelist
func NewIPWhitelister ( whitelistStrings [ ] string ) ( * IPWhiteLister , error ) {
2017-04-30 11:22:07 +02:00
if len ( whitelistStrings ) == 0 {
2017-05-26 17:03:14 +02:00
return nil , errors . New ( "no whitelists provided" )
2017-04-30 11:22:07 +02:00
}
2017-10-10 14:50:03 +02:00
whiteLister := IPWhiteLister { }
2017-07-10 14:58:31 +02:00
2017-10-16 12:46:03 +02:00
ip , err := whitelist . NewIP ( whitelistStrings , false )
2017-10-10 14:50:03 +02:00
if err != nil {
return nil , fmt . Errorf ( "parsing CIDR whitelist %s: %v" , whitelistStrings , err )
2017-04-30 11:22:07 +02:00
}
2017-10-10 14:50:03 +02:00
whiteLister . whiteLister = ip
2017-04-30 11:22:07 +02:00
2017-10-10 14:50:03 +02:00
whiteLister . handler = negroni . HandlerFunc ( whiteLister . handle )
log . Debugf ( "configured %u IP whitelists: %s" , len ( whitelistStrings ) , whitelistStrings )
2017-04-30 11:22:07 +02:00
2017-10-10 14:50:03 +02:00
return & whiteLister , nil
2017-04-30 11:22:07 +02:00
}
2017-10-10 14:50:03 +02:00
func ( wl * IPWhiteLister ) handle ( w http . ResponseWriter , r * http . Request , next http . HandlerFunc ) {
ipAddress , _ , err := net . SplitHostPort ( r . RemoteAddr )
2017-04-30 11:22:07 +02:00
if err != nil {
log . Warnf ( "unable to parse remote-address from header: %s - rejecting" , r . RemoteAddr )
reject ( w )
return
}
2017-10-10 14:50:03 +02:00
allowed , ip , err := wl . whiteLister . Contains ( ipAddress )
if err != nil {
log . Debugf ( "source-IP %s matched none of the whitelists - rejecting" , ipAddress )
reject ( w )
return
2017-04-30 11:22:07 +02:00
}
2017-10-10 14:50:03 +02:00
if allowed {
log . Debugf ( "source-IP %s matched whitelist %s - passing" , ipAddress , wl . whiteLister )
next . ServeHTTP ( w , r )
return
}
log . Debugf ( "source-IP %s matched none of the whitelists - rejecting" , ip )
2017-04-30 11:22:07 +02:00
reject ( w )
}
2017-10-10 14:50:03 +02:00
func ( wl * IPWhiteLister ) ServeHTTP ( rw http . ResponseWriter , r * http . Request , next http . HandlerFunc ) {
wl . handler . ServeHTTP ( rw , r , next )
}
2017-04-30 11:22:07 +02:00
func reject ( w http . ResponseWriter ) {
statusCode := http . StatusForbidden
w . WriteHeader ( statusCode )
w . Write ( [ ] byte ( http . StatusText ( statusCode ) ) )
}