// Parse the "X-Real-IP"/"X-Real-Protocol"/"X-Local-IP" header. func ParseXRealIP(hdr http.Header) (legs []Leg, err error) { r := strings.TrimSpace(hdr.Get("X-Real-IP")) if r == "" { return nil, nil } ip, port, err := denet.FuzzySplitHostPortIPI("", r) if err != nil { return nil, err } p := strings.TrimSpace(hdr.Get("X-Real-Protocol")) r2 := strings.TrimSpace(hdr.Get("X-Local-IP")) var ip2 net.IP var port2 uint16 if r2 != "" { ip2, port2, err = denet.FuzzySplitHostPortIPI("", r2) if err != nil { ip2 = nil port2 = 0 } } return []Leg{Leg{ SourceIP: ip, SourcePort: port, DestinationIP: ip2, DestinationPort: port2, Scheme: p, From: FromXRealIP, }}, nil }
func parseForwarded(forwarded []string) (legs []Leg, err error) { for _, f := range forwarded { leg := Leg{ From: FromForwarded, } for len(f) > 0 { k, v, rest, err := parsePart(f) if err != nil { break } switch k { case "for": ip, port, err := denet.FuzzySplitHostPortIPI("", v) if err != nil { return nil, err } leg.SourceIP, leg.SourcePort = ip, port case "by": ip, port, err := denet.FuzzySplitHostPortIPI("", v) if err != nil { return nil, err } leg.DestinationIP, leg.DestinationPort = ip, port case "proto": leg.Scheme = v case "host": leg.Host = v } f = rest } legs = append(legs, leg) } return }
// Parse the "X-Forwarded-For" header. func ParseXForwardedFor(hdr http.Header) (legs []Leg, err error) { parts := header.ParseList(hdr, "X-Forwarded-For") for _, p := range parts { p = strings.TrimSpace(p) ip, port, err := denet.FuzzySplitHostPortIPI("", p) if err != nil { return nil, err } legs = append(legs, Leg{ SourceIP: ip, SourcePort: port, From: FromXForwardedFor, }) } return }
// Return the local request leg. func ParseLocal(req *http.Request) (legs []Leg, err error) { scheme := "http" if req.TLS != nil { scheme = "https" } ip, port, err := denet.FuzzySplitHostPortIPI("", req.RemoteAddr) if err != nil { return nil, err } return []Leg{Leg{ SourceIP: ip, SourcePort: port, Host: req.Host, Scheme: scheme, From: FromLocal, }}, nil }