-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathsetup.go
143 lines (131 loc) · 2.77 KB
/
setup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package realip
import (
"net"
"strconv"
"github.com/caddyserver/caddy"
"github.com/caddyserver/caddy/caddyhttp/httpserver"
)
func init() {
caddy.RegisterPlugin("realip", caddy.Plugin{
ServerType: "http",
Action: Setup,
})
}
func Setup(c *caddy.Controller) error {
var m *module
for c.Next() {
if m != nil {
return c.Err("cannot specify realip more than once")
}
m = &module{
Header: "X-Forwarded-For",
MaxHops: 5,
}
if err := parse(m, c); err != nil {
return err
}
}
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
m.next = next
return m
})
return nil
}
func parse(m *module, c *caddy.Controller) (err error) {
args := c.RemainingArgs()
if len(args) > 0 {
if err := addIpRanges(m, c, args); err != nil {
return err
}
}
for c.NextBlock() {
var err error
switch c.Val() {
case "header":
m.Header, err = StringArg(c)
case "from":
err = addIpRanges(m, c, c.RemainingArgs())
case "strict":
m.Strict, err = BoolArg(c)
case "maxhops":
m.MaxHops, err = IntArg(c)
default:
return c.Errf("Unknown realip arg: %s", c.Val())
}
if err != nil {
return err
}
}
return nil
}
// Adds a list of CIDR IP Ranges to the From whitelist
func addIpRanges(m *module, c *caddy.Controller, ranges []string) error {
for _, v := range ranges {
if preset, ok := presets[v]; ok {
if err := addIpRanges(m, c, preset); err != nil {
return err
}
continue
}
_, cidr, err := net.ParseCIDR(v)
if err != nil {
return c.Err(err.Error())
}
m.From = append(m.From, cidr)
}
return nil
}
//
// Helpers below here could potentially be methods on *caddy.Controller for convenience
//
// IntArg check's there is only one arg, parses, and returns it
func IntArg(c *caddy.Controller) (int, error) {
args := c.RemainingArgs()
if len(args) != 1 {
return 0, c.ArgErr()
}
return strconv.Atoi(args[0])
}
// Assert only one arg and return it
func StringArg(c *caddy.Controller) (string, error) {
args := c.RemainingArgs()
if len(args) != 1 {
return "", c.ArgErr()
}
return args[0], nil
}
// Assert only one arg is a valid cidr notation
func CidrArg(c *caddy.Controller) (*net.IPNet, error) {
a, err := StringArg(c)
if err != nil {
return nil, err
}
_, cidr, err := net.ParseCIDR(a)
if err != nil {
return nil, err
}
return cidr, nil
}
func BoolArg(c *caddy.Controller) (bool, error) {
args := c.RemainingArgs()
if len(args) > 1 {
return false, c.ArgErr()
}
if len(args) == 0 {
return true, nil
}
switch args[0] {
case "false":
return false, nil
case "true":
return true, nil
default:
return false, c.Errf("Unexpected bool value: %s", args[0])
}
}
func NoArgs(c *caddy.Controller) error {
if len(c.RemainingArgs()) != 0 {
return c.ArgErr()
}
return nil
}