Ability to use "X-Forwarded-For" as a source of IP for white list.

This commit is contained in:
Ludovic Fernandez 2018-03-23 17:40:04 +01:00 committed by Traefiker Bot
parent 4802484729
commit d2766b1b4f
50 changed files with 1496 additions and 599 deletions

View file

@ -1,7 +1,6 @@
package server
import (
"net"
"net/http"
"os"
@ -12,7 +11,7 @@ import (
// NewHeaderRewriter Create a header rewriter
func NewHeaderRewriter(trustedIPs []string, insecure bool) (forward.ReqRewriter, error) {
IPs, err := whitelist.NewIP(trustedIPs, insecure)
IPs, err := whitelist.NewIP(trustedIPs, insecure, true)
if err != nil {
return nil, err
}
@ -38,14 +37,7 @@ type headerRewriter struct {
}
func (h *headerRewriter) Rewrite(req *http.Request) {
clientIP, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
log.Error(err)
h.secureRewriter.Rewrite(req)
return
}
authorized, _, err := h.ips.Contains(clientIP)
authorized, _, err := h.ips.IsAuthorized(req)
if err != nil {
log.Error(err)
h.secureRewriter.Rewrite(req)

View file

@ -326,8 +326,8 @@ func (s *Server) setupServerEntryPoint(newServerEntryPointName string, newServer
}
serverMiddlewares = append(serverMiddlewares, s.globalConfiguration.API.StatsRecorder)
}
}
if s.globalConfiguration.EntryPoints[newServerEntryPointName].Auth != nil {
authMiddleware, err := mauth.NewAuthenticator(s.globalConfiguration.EntryPoints[newServerEntryPointName].Auth, s.tracingMiddleware)
if err != nil {
@ -336,17 +336,22 @@ func (s *Server) setupServerEntryPoint(newServerEntryPointName string, newServer
serverMiddlewares = append(serverMiddlewares, s.wrapNegroniHandlerWithAccessLog(authMiddleware, fmt.Sprintf("Auth for entrypoint %s", newServerEntryPointName)))
serverInternalMiddlewares = append(serverInternalMiddlewares, authMiddleware)
}
if s.globalConfiguration.EntryPoints[newServerEntryPointName].Compress {
serverMiddlewares = append(serverMiddlewares, &middlewares.Compress{})
}
if len(s.globalConfiguration.EntryPoints[newServerEntryPointName].WhitelistSourceRange) > 0 {
ipWhitelistMiddleware, err := middlewares.NewIPWhitelister(s.globalConfiguration.EntryPoints[newServerEntryPointName].WhitelistSourceRange)
if err != nil {
log.Fatal("Error starting server: ", err)
}
ipWhitelistMiddleware, err := buildIPWhiteLister(
s.globalConfiguration.EntryPoints[newServerEntryPointName].WhiteList,
s.globalConfiguration.EntryPoints[newServerEntryPointName].WhitelistSourceRange)
if err != nil {
log.Fatal("Error starting server: ", err)
}
if ipWhitelistMiddleware != nil {
serverMiddlewares = append(serverMiddlewares, s.wrapNegroniHandlerWithAccessLog(ipWhitelistMiddleware, fmt.Sprintf("ipwhitelister for entrypoint %s", newServerEntryPointName)))
serverInternalMiddlewares = append(serverInternalMiddlewares, ipWhitelistMiddleware)
}
newSrv, listener, err := s.prepareServer(newServerEntryPointName, s.globalConfiguration.EntryPoints[newServerEntryPointName], newServerEntryPoint.httpRouter, serverMiddlewares, serverInternalMiddlewares)
if err != nil {
log.Fatal("Error preparing server: ", err)
@ -794,7 +799,7 @@ func (s *Server) prepareServer(entryPointName string, entryPoint *configuration.
}
if entryPoint.ProxyProtocol != nil {
IPs, err := whitelist.NewIP(entryPoint.ProxyProtocol.TrustedIPs, entryPoint.ProxyProtocol.Insecure)
IPs, err := whitelist.NewIP(entryPoint.ProxyProtocol.TrustedIPs, entryPoint.ProxyProtocol.Insecure, false)
if err != nil {
return nil, nil, fmt.Errorf("error creating whitelist: %s", err)
}
@ -1137,13 +1142,16 @@ func (s *Server) loadConfig(configurations types.Configurations, globalConfigura
n.Use(middlewares.NewBackendMetricsMiddleware(s.metricsRegistry, frontend.Backend))
}
ipWhitelistMiddleware, err := configureIPWhitelistMiddleware(frontend.WhitelistSourceRange)
ipWhitelistMiddleware, err := buildIPWhiteLister(frontend.WhiteList, frontend.WhitelistSourceRange)
if err != nil {
log.Errorf("Error creating IP Whitelister: %s", err)
} else if ipWhitelistMiddleware != nil {
ipWhitelistMiddleware = s.wrapNegroniHandlerWithAccessLog(ipWhitelistMiddleware, fmt.Sprintf("ipwhitelister for %s", frontendName))
n.Use(s.tracingMiddleware.NewNegroniHandlerWrapper("IP whitelist", ipWhitelistMiddleware, false))
log.Infof("Configured IP Whitelists: %s", frontend.WhitelistSourceRange)
n.Use(
s.tracingMiddleware.NewNegroniHandlerWrapper(
"IP whitelist",
s.wrapNegroniHandlerWithAccessLog(ipWhitelistMiddleware, fmt.Sprintf("ipwhitelister for %s", frontendName)),
false))
log.Debugf("Configured IP Whitelists: %s", frontend.WhitelistSourceRange)
}
if frontend.Redirect != nil && entryPointName != frontend.Redirect.EntryPoint {
@ -1256,18 +1264,13 @@ func (s *Server) configureLBServers(lb healthcheck.LoadBalancer, config *types.C
return nil
}
func configureIPWhitelistMiddleware(whitelistSourceRanges []string) (negroni.Handler, error) {
if len(whitelistSourceRanges) > 0 {
ipSourceRanges := whitelistSourceRanges
ipWhitelistMiddleware, err := middlewares.NewIPWhitelister(ipSourceRanges)
if err != nil {
return nil, err
}
return ipWhitelistMiddleware, nil
func buildIPWhiteLister(whiteList *types.WhiteList, wlRange []string) (*middlewares.IPWhiteLister, error) {
if whiteList != nil &&
len(whiteList.SourceRange) > 0 {
return middlewares.NewIPWhiteLister(whiteList.SourceRange, whiteList.UseXForwardedFor)
} else if len(wlRange) > 0 {
return middlewares.NewIPWhiteLister(wlRange, false)
}
return nil, nil
}

View file

@ -571,48 +571,75 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
}
}
func TestNewServerWithWhitelistSourceRange(t *testing.T) {
cases := []struct {
func TestBuildIPWhiteLister(t *testing.T) {
testCases := []struct {
desc string
whitelistStrings []string
whitelistSourceRange []string
whiteList *types.WhiteList
middlewareConfigured bool
errMessage string
}{
{
desc: "no whitelists configued",
whitelistStrings: nil,
desc: "no whitelists configured",
whitelistSourceRange: nil,
middlewareConfigured: false,
errMessage: "",
}, {
desc: "whitelists configued",
whitelistStrings: []string{
},
{
desc: "whitelists configured (deprecated)",
whitelistSourceRange: []string{
"1.2.3.4/24",
"fe80::/16",
},
middlewareConfigured: true,
errMessage: "",
}, {
desc: "invalid whitelists configued",
whitelistStrings: []string{
},
{
desc: "invalid whitelists configured (deprecated)",
whitelistSourceRange: []string{
"foo",
},
middlewareConfigured: false,
errMessage: "parsing CIDR whitelist [foo]: parsing CIDR whitelist <nil>: invalid CIDR address: foo",
errMessage: "parsing CIDR whitelist [foo]: parsing CIDR white list <nil>: invalid CIDR address: foo",
},
{
desc: "whitelists configured",
whiteList: &types.WhiteList{
SourceRange: []string{
"1.2.3.4/24",
"fe80::/16",
},
UseXForwardedFor: false,
},
middlewareConfigured: true,
errMessage: "",
},
{
desc: "invalid whitelists configured (deprecated)",
whiteList: &types.WhiteList{
SourceRange: []string{
"foo",
},
UseXForwardedFor: false,
},
middlewareConfigured: false,
errMessage: "parsing CIDR whitelist [foo]: parsing CIDR white list <nil>: invalid CIDR address: foo",
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.desc, func(t *testing.T) {
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
middleware, err := configureIPWhitelistMiddleware(tc.whitelistStrings)
if tc.errMessage != "" {
require.EqualError(t, err, tc.errMessage)
middleware, err := buildIPWhiteLister(test.whiteList, test.whitelistSourceRange)
if test.errMessage != "" {
require.EqualError(t, err, test.errMessage)
} else {
assert.NoError(t, err)
if tc.middlewareConfigured {
if test.middlewareConfigured {
require.NotNil(t, middleware, "not expected middleware to be configured")
} else {
require.Nil(t, middleware, "expected middleware to be configured")