Git Product home page Git Product logo

proxyprotocol's Introduction

proxyprotocol

GoDoc Build Status

This package provides PROXY protocol support for versions 1 and 2.

https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt

Features:

  • Auto detect both V1 and V2
  • Client & Server usage support
  • Listener with optional subnet filtering (for TCP/UDP listeners)

Installation

Installable via go get

go get -u github.com/mastercactapus/proxyprotocol

Usage

// Create any net.Listener
l, err := net.Listen("tcp", ":0")
l, err := net.Listen("udp", ":0")
l, err := net.Listen("unix", "/tmp/example")
l, err := net.Listen("unixgram", "/tmp/example")

// Wrap it to have RemoteAddr() and LocalAddr() resolved for all new connections
l = proxyprotocol.NewListener(l, 0)

c, err : = l.Accept()

c.RemoteAddr() // = The PROXY header source address
c.LocalAddr()  // = The PROXY header destination address

proxyprotocol's People

Contributors

mastercactapus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

proxyprotocol's Issues

"Invalid source address" when proxy header contains IPv4-mapped IPv6 address

I encountered this using caddy-l4 which depends on this project. I opened mholt/caddy-l4#91 but later realized I should open an issue here.

Consider the following proxy protocol header (which is passed by haproxy in my environment):

PROXY TCP6 ::ffff:192.168.0.1 ::ffff:192.168.0.1 53740 10001

Given this header, parseV1() returns the error "invalid source address." The reason seems to be this line because net.IP.To4() will return non-nil when ParseIP() parses a v4-mapped IPv6 address.

Invalid V2 PROXY data causes parsing panics/denial-of-service

๐Ÿ‘‹ hi @mastercactapus, I was looking into the HAProxy V2 PROXY protocol and found your package. Unfortunately I found a class of crasher bugs when the library is presented malformed input.

The headerv2.go's parseV2 function doesn't validate that the length of the buffered data is large enough to ensure that the slicing done to extract src/dest IP addresses (and ports where applicable) won't be out of bounds.

Here's a small reproduction program:

package main

import (
	"bufio"
	"bytes"

	"github.com/mastercactapus/proxyprotocol"
)

func main() {
	data := []byte{
		// PROXY protocol v2 magic header
		0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A,
		// v2 version, PROXY cmd
		0x21,
		// TCP, IPv4 (also works with 0x13,0x21,0x22,0x31,0x32)
		0x12,
		// Length
		0x00, 0x00,
		// src/dest address data _should_ be here but is omitted.
	}

	/*
		panic: runtime error: slice bounds out of range

		goroutine 1 [running]:
		github.com/mastercactapus/proxyprotocol.parseV2(0xc00005e180, 0x100d, 0x0, 0x0)
			/home/daniel/go/src/github.com/mastercactapus/proxyprotocol/headerv2.go:93 +0x18e4
		github.com/mastercactapus/proxyprotocol.Parse(0xc00005e180, 0x1000, 0x1000, 0xc000086000, 0x459a3d)
			/home/daniel/go/src/github.com/mastercactapus/proxyprotocol/parse.go:31 +0x149
		main.main()
			/home/daniel/test.go:21 +0x18f
		exit status 2
	*/
	_, _ = proxyprotocol.Parse(
		bufio.NewReader(
			bytes.NewReader(data)))
}

The inline comment shows where the panic occurs. You can change the panic location by switching the 0x12 byte to one of the other supported FamProto values in the parsing switch statement. All supported FamProto's are affected by this class of bug.

Notably this results in a trivial denial of service attack against upstream consumers of this package. I was able to reproduce this crash with your caddy-proxyprotocol plugin, Caddy v1.0.1 and the following Caddy file:

beta.threeletter.agency:443

log access.log

root /var/www/test

proxyprotocol {
  timeout 3s
}

Here's the output from the Caddy server after receiving the payload from the reproduction above:

#> caddy -version
Caddy v1.0.1 (h1:oor6ep+8NoJOabpFXhvjqjfeldtw1XSzfISVrbfqTKo=)

#> caddy -conf caddy.conf 
Activating privacy features... done.

Serving HTTPS on port 443 
https://beta.threeletter.agency


Serving HTTP on port 80 
http://beta.threeletter.agency

WARNING: File descriptor limit 1024 is too low for production servers. At least 8192 is recommended. Fix with `ulimit -n 8192`.
panic: runtime error: slice bounds out of range

goroutine 20 [running]:
github.com/mastercactapus/proxyprotocol.parseV2(0xc00006d6e0, 0xc00006d70d, 0x0, 0x0)
	/tmp/buildenv_07-17-1625.973213325/main/vendor/github.com/mastercactapus/proxyprotocol/headerv2.go:93 +0x18e4
github.com/mastercactapus/proxyprotocol.Parse(0xc00006d6e0, 0xd7aa80, 0xc00000e6e0, 0x0, 0x0)
	/tmp/buildenv_07-17-1625.973213325/main/vendor/github.com/mastercactapus/proxyprotocol/parse.go:31 +0x149
github.com/mastercactapus/proxyprotocol.(*Conn).parse(0xc000140280)
	/tmp/buildenv_07-17-1625.973213325/main/vendor/github.com/mastercactapus/proxyprotocol/conn.go:47 +0x109
sync.(*Once).Do(0xc0001402a0, 0xc0000504b0)
	/usr/local/go/src/sync/once.go:44 +0xb3
github.com/mastercactapus/proxyprotocol.(*Conn).RemoteAddr(0xc000140280, 0x0, 0x0)
	/tmp/buildenv_07-17-1625.973213325/main/vendor/github.com/mastercactapus/proxyprotocol/conn.go:70 +0x58
crypto/tls.(*Conn).RemoteAddr(0xc000168e00, 0x0, 0x0)
	/usr/local/go/src/crypto/tls/conn.go:124 +0x33
net/http.(*conn).serve(0xc000140320, 0xd731c0, 0xc0001431a0)
	/usr/local/go/src/net/http/server.go:1763 +0x4c
created by net/http.(*Server).Serve

I think its likely worth treating this as a denial of service vulnerability and releasing a new version of both this library and the upstream caddy-proxyprotocol plugin with a note indicating users should upgrade. As an additional note because of when this panic occurs there is no audit trail in the configured access.log and it brings down the entire webserver, not just the Go routine handling the request.

Unfortunately I don't have the cycles to develop a fix for this bug. I'm not a Caddy user or a caddy-proxyprotocol user, just a curious dev.

Making sure Caddy 2 can handle the proxyprotocol plugin

Hi Nathaniel, hope all is well! This is not an issue that needs you to do anything, really. It's more for discussion, and it's totally optional. I am just looking at making sure Caddy 2 will be able to support the PROXY protocol, likely via a plugin (called a "module" in Caddy 2).

In Caddy 2, listeners are configured simply by giving a list of addresses, as strings: "listen": ["localhost:5000", "localhost:8080"] for example.

I think this concise format is pretty useful for the majority of use cases, but it makes it hard to define listeners which need custom behavior at the network level (as opposed to the HTTP or application level). Clearly we need to support listener "middleware" like we do in v1.

So I was thinking of a new property called listen_advanced (or something) that allows one to define a listener with custom/modular behavior:

{
    "listen_advanced": {
        "addresses": ["localhost:5000",  "localhost:8080"],
        "modules": [
            {
                "listener_module": "proxy_protocol",
                "other": "config goes here"
            }
        ]
    }
}

Anyway, just thought I'd check with you if you had any opinions on the matter, or requests for a v2 way of doing this. If it sounds good to you, feel free to just let me know and close this issue, thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.