-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtcp.go
151 lines (118 loc) · 3.1 KB
/
tcp.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
144
145
146
147
148
149
150
151
package ngroklistener
import (
"fmt"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"go.uber.org/zap"
"golang.ngrok.com/ngrok/config"
)
func init() {
caddy.RegisterModule(new(TCP))
}
// ngrok TCP tunnel
type TCP struct {
opts []config.TCPEndpointOption
// The remote TCP address to request for this edge
RemoteAddr string `json:"remote_addr,omitempty"`
// opaque metadata string for this tunnel.
Metadata string `json:"metadata,omitempty"`
// Rejects connections that do not match the given CIDRs
AllowCIDR []string `json:"allow_cidr,omitempty"`
// Rejects connections that match the given CIDRs and allows all other CIDRs.
DenyCIDR []string `json:"deny_cidr,omitempty"`
l *zap.Logger
}
// Provision implements caddy.Provisioner
func (t *TCP) Provision(ctx caddy.Context) error {
t.l = ctx.Logger()
t.doReplace()
if err := t.provisionOpts(); err != nil {
return fmt.Errorf("provisioning tcp tunnel opts: %v", err)
}
return nil
}
func (t *TCP) provisionOpts() error {
if t.RemoteAddr != "" {
t.opts = append(t.opts, config.WithRemoteAddr(t.RemoteAddr))
}
if t.Metadata != "" {
t.opts = append(t.opts, config.WithMetadata(t.Metadata))
}
if len(t.AllowCIDR) > 0 {
t.opts = append(t.opts, config.WithAllowCIDRString(t.AllowCIDR...))
}
if len(t.DenyCIDR) > 0 {
t.opts = append(t.opts, config.WithDenyCIDRString(t.DenyCIDR...))
}
return nil
}
func (t *TCP) doReplace() {
repl := caddy.NewReplacer()
replaceableFields := []*string{
&t.Metadata,
}
for _, field := range replaceableFields {
actual := repl.ReplaceKnown(*field, "")
*field = actual
}
for index, cidr := range t.AllowCIDR {
actual := repl.ReplaceKnown(cidr, "")
t.AllowCIDR[index] = actual
}
for index, cidr := range t.DenyCIDR {
actual := repl.ReplaceKnown(cidr, "")
t.DenyCIDR[index] = actual
}
}
// convert to ngrok's Tunnel type
func (t *TCP) NgrokTunnel() config.Tunnel {
return config.TCPEndpoint(t.opts...)
}
// CaddyModule implements caddy.Module
func (*TCP) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "caddy.listeners.ngrok.tunnels.tcp",
New: func() caddy.Module {
return new(TCP)
},
}
}
func (t *TCP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
for d.Next() {
if d.NextArg() {
return d.ArgErr()
}
for nesting := d.Nesting(); d.NextBlock(nesting); {
subdirective := d.Val()
switch subdirective {
case "metadata":
if !d.AllArgs(&t.Metadata) {
return d.ArgErr()
}
case "remote_addr":
if !d.AllArgs(&t.RemoteAddr) {
return d.ArgErr()
}
case "allow":
if d.CountRemainingArgs() == 0 {
return d.ArgErr()
}
t.AllowCIDR = append(t.AllowCIDR, d.RemainingArgs()...)
case "deny":
if d.CountRemainingArgs() == 0 {
return d.ArgErr()
}
t.DenyCIDR = append(t.DenyCIDR, d.RemainingArgs()...)
default:
return d.Errf("unrecognized subdirective %s", subdirective)
}
}
}
return nil
}
var (
_ caddy.Module = (*TCP)(nil)
_ Tunnel = (*TCP)(nil)
_ caddy.Provisioner = (*TCP)(nil)
_ caddyfile.Unmarshaler = (*TCP)(nil)
)