Skip to content

Commit

Permalink
fix: improve ipv6 handling and logging
Browse files Browse the repository at this point in the history
fix: improve ipv6 handling and logging
  • Loading branch information
rdoorn authored Nov 12, 2019
1 parent ccd65ea commit ad8a419
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 35 deletions.
7 changes: 3 additions & 4 deletions pkg/proxy/proxy_acl_cidr.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,24 @@ package proxy
import (
"fmt"
"net"
"strings"

"github.com/schubergphilis/mercury/pkg/logging"
)

// processHeader calls the correct handler when editing headers
func (acl ACL) processCIDR(addr string) (match bool) {
log := logging.For("proxy/processcidr")
ip := strings.Split(addr, ":")[0]
clientAddr := stringToClientIP(addr)

for _, network := range acl.CIDRS {
_, ipnetA, err := net.ParseCIDR(network)
if err != nil {
log.Printf("Error parsing CIRD:%s error: %s\n", network, err)
}

ipB, _, err := net.ParseCIDR(fmt.Sprintf("%s/32", ip))
ipB, _, err := net.ParseCIDR(fmt.Sprintf("%s/32", clientAddr.IP))
if err != nil {
log.Printf("Error parsing CIRD:%s error: %s\n", fmt.Sprintf("%s/32", ip), err)
log.Printf("Error parsing CIRD:%s error: %s\n", fmt.Sprintf("%s/32", clientAddr.IP), err)
}

if ipnetA.Contains(ipB) {
Expand Down
29 changes: 29 additions & 0 deletions pkg/proxy/proxy_generic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package proxy

import (
"strconv"
"strings"
)

type clientIP struct {
IP string
Port int
}

func stringToClientIP(addr string) *clientIP {
client := &clientIP{}
remoteAddr := strings.Split(addr, ":")
// if we have no port, assume its an IP only
if len(remoteAddr) == 1 {
client.IP = addr
return client
}
// if we have a port definition check wether its ipv6 or a real port number
if len(remoteAddr) > 1 {
client.IP = strings.Join(remoteAddr[:len(remoteAddr)-1], ":")
if port, err := strconv.Atoi(remoteAddr[len(remoteAddr)-1]); err == nil {
client.Port = port
}
}
return client
}
18 changes: 18 additions & 0 deletions pkg/proxy/proxy_generic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package proxy

import "testing"
import "github.com/stretchr/testify/assert"

func TestIPConversion(t *testing.T) {
client := stringToClientIP("10.11.12.13")
assert.Equal(t, "10.11.12.13", client.IP)
assert.Equal(t, 0, client.Port)

client = stringToClientIP("10.11.12.13:23")
assert.Equal(t, "10.11.12.13", client.IP)
assert.Equal(t, 23, client.Port)

client = stringToClientIP("fe80::493d:d242:9475:a510:23")
assert.Equal(t, "fe80::493d:d242:9475:a510", client.IP)
assert.Equal(t, 23, client.Port)
}
16 changes: 10 additions & 6 deletions pkg/proxy/proxy_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,12 @@ func getVariableValue(name string, l *Listener, backendnode *BackendNode, req *h
return "http", nil

case "CLIENT_IP":
val := strings.Split(req.RemoteAddr, ":")
return val[0], nil
clientAddr := stringToClientIP(req.RemoteAddr)
return clientAddr.IP, nil

case "CLIENT_PORT":
clientAddr := stringToClientIP(req.RemoteAddr)
return strconv.Itoa(clientAddr.Port), nil

case "CLIENT_CERT":
return getClientCertValue(req)
Expand Down Expand Up @@ -307,8 +311,9 @@ func (l *Listener) NewHTTPProxy() *httputil.ReverseProxy {
// - applies inbound ACL's (to be sent to the backend server)
// - sets the url Scheme to be processed by the RoundTrip handler, and the ModifyResponse handler
director := func(req *http.Request) {
remoteAddr := strings.Split(req.RemoteAddr, ":")
clog := log.WithField("clientip", remoteAddr[0]).WithField("hostname", req.Host)
clientAddr := stringToClientIP(req.RemoteAddr)

clog := log.WithField("clientip", clientAddr.IP).WithField("hostname", req.Host)
// Update statistics of the Listener
l.Statistics.ClientsConnectsAdd(1)
l.updateClients()
Expand Down Expand Up @@ -361,8 +366,7 @@ func (l *Listener) NewHTTPProxy() *httputil.ReverseProxy {
}

// Get a Node to balance this request to
client := strings.Split(req.RemoteAddr, ":")
backendnode, status, err := backend.GetBackendNodeBalanced(backendname, client[0], stickyCookie, backend.BalanceMode)
backendnode, status, err := backend.GetBackendNodeBalanced(backendname, clientAddr.IP, stickyCookie, backend.BalanceMode)
if err != nil {
clog.WithField("error", err).Error("No backend node available")
if status == healthcheck.Maintenance {
Expand Down
19 changes: 0 additions & 19 deletions pkg/proxy/proxy_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"io/ioutil"
"net/http"
"reflect"
"strconv"
"strings"

"github.com/rdoorn/gorule"
)
Expand Down Expand Up @@ -159,20 +157,3 @@ if len(l.Backends[backendname].InboundRule) > 0 {
}
*/

type clientIP struct {
IP string
Port int
}

func stringToClientIP(addr string) *clientIP {
client := &clientIP{}
remoteAddr := strings.Split(addr, ":")
if len(remoteAddr) > 1 {
client.IP = strings.Join(remoteAddr[:len(remoteAddr)-1], ":")
if port, err := strconv.Atoi(remoteAddr[len(remoteAddr)-1]); err == nil {
client.Port = port
}
}
return client
}
9 changes: 4 additions & 5 deletions pkg/proxy/proxy_tcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"io"
"net"
"strings"
"time"

"github.com/schubergphilis/mercury/pkg/healthcheck"
Expand Down Expand Up @@ -50,8 +49,8 @@ func (l *Listener) TCPProxy(n net.Listener) {

// Handler handles clients and connectors proxys
func (l *Listener) Handler(client net.Conn) {
clientip := strings.Split(client.RemoteAddr().String(), ":")
log := logging.For("proxy/tcp/handler").WithField("pool", l.Name).WithField("localip", l.IP).WithField("localport", l.Port).WithField("clientip", clientip[0]).WithField("clientaddr", client.RemoteAddr())
clientAddr := stringToClientIP(client.RemoteAddr().String())
log := logging.For("proxy/tcp/handler").WithField("pool", l.Name).WithField("localip", l.IP).WithField("localport", l.Port).WithField("clientip", clientAddr.IP).WithField("clientaddr", client.RemoteAddr())
if l.SourceIP != "" {
log = log.WithField("sourceip", l.SourceIP)
}
Expand All @@ -77,7 +76,7 @@ func (l *Listener) Handler(client net.Conn) {
// Process all ACL's and count hit's if any
aclsHit := 0
for _, inacl := range backend.InboundACL {
if inacl.ProcessTCPRequest(clientip[0]) { // process request returns true if we match a allow/deny acl
if inacl.ProcessTCPRequest(clientAddr.IP) { // process request returns true if we match a allow/deny acl
aclsHit++
}
}
Expand All @@ -97,7 +96,7 @@ func (l *Listener) Handler(client net.Conn) {
return
}

node, status, err := backend.GetBackendNodeBalanced(l.Name, clientip[0], "stickyness_not_supported_in_tcp_lb", backend.BalanceMode)
node, status, err := backend.GetBackendNodeBalanced(l.Name, clientAddr.IP, "stickyness_not_supported_in_tcp_lb", backend.BalanceMode)
if err != nil {
if status == healthcheck.Maintenance {
log.WithError(err).Error("No backend available")
Expand Down
2 changes: 1 addition & 1 deletion test/mercury-template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ connectmode = "https"
inboundrules = [
'''
if $(request.host) regex example.com {
request.host = "www.ghostbox.org"
request.host = "another-backend-host.example.com"
}
''',
'''
Expand Down

0 comments on commit ad8a419

Please sign in to comment.