Skip to content

Commit 3939c24

Browse files
initial commit
0 parents  commit 3939c24

3 files changed

Lines changed: 148 additions & 0 deletions

File tree

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Add PROXY protocol support to caddy
2+
3+
## Syntax
4+
5+
```
6+
proxyprotocol *cidr* ... {
7+
timeout *val*
8+
}
9+
```
10+
11+
- **cidr** CIDR ranges to process PROXY headers from
12+
- **val** duration value (e.g. 5s, 1m)
13+
14+
The default timeout is `5s`. Set to `0` or `none` to disable the timeout.
15+
16+
## Examples
17+
18+
```
19+
# Enable from any source (probably don't want this in prod)
20+
proxyprotocol
21+
22+
# Enable from local subnet and fixed IP
23+
proxyprotocol 10.22.0.0/16 10.23.0.1/32
24+
25+
# Set header timeout
26+
proxyprotocol 10.22.0.0/16 10.23.0.1/32 {
27+
timeout 5s
28+
}
29+
30+
```

listeners.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package proxyprotocol
2+
3+
import (
4+
"net"
5+
"os"
6+
7+
proxyproto "github.com/armon/go-proxyproto"
8+
"github.com/mholt/caddy"
9+
)
10+
11+
type Configs []Config
12+
13+
type Listener struct {
14+
net.Listener
15+
Configs []Config
16+
}
17+
type CaddyListener struct {
18+
*Listener
19+
}
20+
21+
func (c *CaddyListener) File() (*os.File, error) {
22+
return c.Listener.Listener.(caddy.Listener).File()
23+
}
24+
25+
func (c Configs) NewListener(l net.Listener) net.Listener {
26+
ln := &Listener{
27+
Listener: l,
28+
Configs: []Config(c),
29+
}
30+
if _, ok := l.(caddy.Listener); ok {
31+
return &CaddyListener{Listener: ln}
32+
}
33+
return ln
34+
}
35+
36+
func (l *Listener) Accept() (net.Conn, error) {
37+
c, err := l.Listener.Accept()
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
addr, ok := c.RemoteAddr().(*net.TCPAddr)
43+
if !ok {
44+
return c, nil
45+
}
46+
for _, cfg := range l.Configs {
47+
if cfg.Subnets == nil {
48+
return proxyproto.NewConn(c, cfg.Timeout), nil
49+
}
50+
for _, s := range cfg.Subnets {
51+
if s.Contains(addr.IP) {
52+
return proxyproto.NewConn(c, cfg.Timeout), nil
53+
}
54+
}
55+
}
56+
return c, nil
57+
}

setup.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package proxyprotocol
2+
3+
import (
4+
"net"
5+
"time"
6+
7+
"github.com/mholt/caddy"
8+
"github.com/mholt/caddy/caddyhttp/httpserver"
9+
)
10+
11+
type Config struct {
12+
Timeout time.Duration
13+
Subnets []*net.IPNet
14+
}
15+
16+
func init() {
17+
caddy.RegisterPlugin("proxyprotocol", caddy.Plugin{
18+
ServerType: "http",
19+
Action: setup,
20+
})
21+
}
22+
23+
func setup(c *caddy.Controller) error {
24+
var configs []Config
25+
var err error
26+
27+
for c.Next() {
28+
var cfg Config
29+
for c.NextArg() {
30+
_, n, err := net.ParseCIDR(c.Val())
31+
if err != nil {
32+
return err
33+
}
34+
cfg.Subnets = append(cfg.Subnets, n)
35+
}
36+
37+
if c.NextBlock() {
38+
switch c.Val() {
39+
case "timeout":
40+
if !c.NextArg() {
41+
return c.ArgErr()
42+
}
43+
cfg.Timeout, err = time.ParseDuration(c.Val())
44+
if err != nil {
45+
return err
46+
}
47+
default:
48+
return c.ArgErr()
49+
}
50+
}
51+
configs = append(configs, cfg)
52+
if c.NextBlock() {
53+
return c.ArgErr()
54+
}
55+
}
56+
if configs != nil {
57+
httpserver.GetConfig(c).AddListenerMiddleware(Configs(configs).NewListener)
58+
}
59+
60+
return nil
61+
}

0 commit comments

Comments
 (0)