-
Notifications
You must be signed in to change notification settings - Fork 0
/
firewall.go
110 lines (97 loc) · 3.08 KB
/
firewall.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
// Copyright 2017 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package network
import (
"fmt"
"net"
"sort"
"strings"
"github.com/juju/errors"
)
// IngressRule represents a range of ports and sources
// from which to allow ingress by incoming packets.
type IngressRule struct {
// PortRange is the range of ports for which incoming
// packets are allowed.
PortRange
// SourceCIDRs is a list of IP address blocks expressed in CIDR format
// to which this rule applies.
SourceCIDRs []string
}
// NewIngressRule returns an IngressRule for the specified port
// range. If no explicit source ranges are specified, there is no
// restriction from where incoming traffic originates.
func NewIngressRule(protocol string, from, to int, sourceCIDRs ...string) (IngressRule, error) {
rule := IngressRule{
PortRange: PortRange{
Protocol: protocol,
FromPort: from,
ToPort: to,
},
}
for _, cidr := range sourceCIDRs {
if _, _, err := net.ParseCIDR(cidr); err != nil {
return IngressRule{}, errors.Trace(err)
}
}
if len(sourceCIDRs) > 0 {
rule.SourceCIDRs = sourceCIDRs
}
return rule, nil
}
// MustNewIngressRule returns an IngressRule for the specified port
// range. If no explicit source ranges are specified, there is no
// restriction from where incoming traffic originates.
// The method will panic if there is an error.
func MustNewIngressRule(protocol string, from, to int, sourceCIDRs ...string) IngressRule {
rule, err := NewIngressRule(protocol, from, to, sourceCIDRs...)
if err != nil {
panic(err)
}
return rule
}
// NewOpenIngressRule returns an IngressRule for the specified port
// range. There is no restriction from where incoming traffic originates.
func NewOpenIngressRule(protocol string, from, to int) IngressRule {
rule, _ := NewIngressRule(protocol, from, to)
return rule
}
// String is the string representation of IngressRule.
func (r IngressRule) String() string {
source := ""
from := strings.Join(r.SourceCIDRs, ",")
if from != "" && from != "0.0.0.0/0" {
source = " from " + from
}
if r.FromPort == r.ToPort {
return fmt.Sprintf("%d/%s%s", r.FromPort, strings.ToLower(r.Protocol), source)
}
return fmt.Sprintf("%d-%d/%s%s", r.FromPort, r.ToPort, strings.ToLower(r.Protocol), source)
}
// GoString is used to print values passed as an operand to a %#v format.
func (r IngressRule) GoString() string {
return r.String()
}
type IngressRuleSlice []IngressRule
func (p IngressRuleSlice) Len() int { return len(p) }
func (p IngressRuleSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p IngressRuleSlice) Less(i, j int) bool {
p1 := p[i]
p2 := p[j]
if p1.Protocol != p2.Protocol {
return p1.Protocol < p2.Protocol
}
if p1.FromPort != p2.FromPort {
return p1.FromPort < p2.FromPort
}
if p1.ToPort != p2.ToPort {
return p1.ToPort < p2.ToPort
}
s1 := strings.Join(p1.SourceCIDRs, ",")
s2 := strings.Join(p2.SourceCIDRs, ",")
return s1 < s2
}
// SortIngressRules sorts the given rules, first by protocol, then by ports.
func SortIngressRules(IngressRules []IngressRule) {
sort.Sort(IngressRuleSlice(IngressRules))
}