-
Notifications
You must be signed in to change notification settings - Fork 18.7k
/
proxy.go
85 lines (77 loc) · 1.81 KB
/
proxy.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
package portmapper
import (
"fmt"
"io"
"net"
"github.com/ishidawataru/sctp"
)
// ipVersion refers to IP version - v4 or v6
type ipVersion string
const (
// IPv4 is version 4
ipv4 ipVersion = "4"
// IPv4 is version 6
ipv6 ipVersion = "6"
)
// dummyProxy just listen on some port, it is needed to prevent accidental
// port allocations on bound port, because without userland proxy we using
// iptables rules and not net.Listen
type dummyProxy struct {
listener io.Closer
addr net.Addr
ipVersion ipVersion
}
func newDummyProxy(proto string, hostIP net.IP, hostPort int) (stop func() error, retErr error) {
// detect version of hostIP to bind only to correct version
version := ipv4
if hostIP.To4() == nil {
version = ipv6
}
var addr net.Addr
switch proto {
case "tcp":
addr = &net.TCPAddr{IP: hostIP, Port: hostPort}
case "udp":
addr = &net.UDPAddr{IP: hostIP, Port: hostPort}
case "sctp":
addr = &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: hostIP}}, Port: hostPort}
default:
return nil, fmt.Errorf("Unknown addr type: %s", proto)
}
p := &dummyProxy{addr: addr, ipVersion: version}
if err := p.start(); err != nil {
return nil, err
}
return p.stop, nil
}
func (p *dummyProxy) start() error {
switch addr := p.addr.(type) {
case *net.TCPAddr:
l, err := net.ListenTCP("tcp"+string(p.ipVersion), addr)
if err != nil {
return err
}
p.listener = l
case *net.UDPAddr:
l, err := net.ListenUDP("udp"+string(p.ipVersion), addr)
if err != nil {
return err
}
p.listener = l
case *sctp.SCTPAddr:
l, err := sctp.ListenSCTP("sctp"+string(p.ipVersion), addr)
if err != nil {
return err
}
p.listener = l
default:
return fmt.Errorf("Unknown addr type: %T", p.addr)
}
return nil
}
func (p *dummyProxy) stop() error {
if p.listener != nil {
return p.listener.Close()
}
return nil
}