7
7
"strings"
8
8
9
9
"github.com/docker/docker/libnetwork/iptables"
10
+ "github.com/psviderski/uncloud/internal/machine/constants"
11
+ "github.com/psviderski/uncloud/internal/machine/corroservice"
10
12
"github.com/psviderski/uncloud/internal/machine/network"
11
13
)
12
14
@@ -17,86 +19,138 @@ const (
17
19
18
20
// ConfigureIptablesChains sets up custom iptables chains and initial firewall rules for Uncloud networking.
19
21
func ConfigureIptablesChains () error {
20
- // Ensure iptables UNCLOUD-INPUT chain exists. All existing rules are flushed.
21
- ipt := iptables .GetIptable (iptables .IPv4 )
22
- if _ , err := ipt .NewChain (UncloudInputChain , iptables .Filter ); err != nil {
23
- return fmt .Errorf ("create iptables chain '%s': %w" , UncloudInputChain , err )
22
+ if err := createIptablesChains (); err != nil {
23
+ return err
24
24
}
25
- if err := ipt .RawCombinedOutput ("-t" , string (iptables .Filter ), "-F" , UncloudInputChain ); err != nil {
26
- return fmt .Errorf ("flush iptables chain '%s': %w" , UncloudInputChain , err )
25
+
26
+ ipt4 := iptables .GetIptable (iptables .IPv4 )
27
+ ipt6 := iptables .GetIptable (iptables .IPv6 )
28
+
29
+ // Allow WireGuard traffic to the machine.
30
+ acceptWireGuardRule := []string {"-p" , "udp" , "--dport" , strconv .Itoa (network .WireGuardPort ), "-j" , "ACCEPT" }
31
+ err := ipt4 .ProgramRule (iptables .Filter , UncloudInputChain , iptables .Insert , acceptWireGuardRule )
32
+ if err != nil {
33
+ return fmt .Errorf ("insert iptables rule '%s': %w" , strings .Join (acceptWireGuardRule , " " ), err )
27
34
}
28
35
29
- // Ensure the main iptables INPUT chain has a jump rule to the UNCLOUD-INPUT chain before any DROP/REJECT rules.
30
- jumpRule := []string {"-m" , "comment" , "--comment" , "Uncloud-managed" , "-j" , UncloudInputChain }
31
- if ! ipt .Exists (iptables .Filter , "INPUT" , jumpRule ... ) {
32
- // Look for the first DROP/REJECT rule in the INPUT chain.
33
- out , err := ipt .Raw ("-t" , string (iptables .Filter ), "-L" , "INPUT" , "--line-numbers" )
34
- if err != nil {
35
- return fmt .Errorf ("get iptables rules for chain '%s': %w" , UncloudInputChain , err )
36
+ // Allow cluster machines to access Machine API via the management IPv6 WireGuard network.
37
+ acceptMachineAPIRule := []string {
38
+ "-i" , network .WireGuardInterfaceName ,
39
+ "-s" , "fdcc::/16" ,
40
+ "-p" , "tcp" ,
41
+ "--dport" , strconv .Itoa (constants .MachineAPIPort ),
42
+ "-j" , "ACCEPT" ,
43
+ }
44
+ // Allow Corrosion gossip traffic from cluster machines via the management IPv6 WireGuard network.
45
+ acceptCorrosionGossipRule := []string {
46
+ "-i" , network .WireGuardInterfaceName ,
47
+ "-s" , "fdcc::/16" ,
48
+ "-p" , "udp" ,
49
+ "--dport" , strconv .Itoa (corroservice .DefaultGossipPort ),
50
+ "-j" , "ACCEPT" ,
51
+ }
52
+ for _ , rule := range [][]string {acceptMachineAPIRule , acceptCorrosionGossipRule } {
53
+ if err = ipt6 .ProgramRule (iptables .Filter , UncloudInputChain , iptables .Insert , rule ); err != nil {
54
+ return fmt .Errorf ("insert ip6tables rule '%s': %w" , strings .Join (rule , " " ), err )
36
55
}
56
+ }
37
57
38
- firstRejectRuleNum := 0
39
- for _ , line := range strings .Split (string (out ), "\n " ) {
40
- fields := strings .Fields (line )
41
- if len (fields ) < 2 {
42
- continue
43
- }
44
- if fields [1 ] == "DROP" || fields [1 ] == "REJECT" {
45
- if ruleNum , err := strconv .Atoi (fields [0 ]); err == nil {
46
- firstRejectRuleNum = ruleNum
47
- break
48
- }
49
- }
58
+ return nil
59
+ }
60
+
61
+ // createIptablesChains ensures UNCLOUD-INPUT iptables and ip6tables chains exist and
62
+ // there are jump rules from the main INPUT chains.
63
+ func createIptablesChains () error {
64
+ ipt4 := iptables .GetIptable (iptables .IPv4 )
65
+ ipt6 := iptables .GetIptable (iptables .IPv6 )
66
+
67
+ for i , ipt := range []* iptables.IPTable {ipt4 , ipt6 } {
68
+ iptBin := "iptables"
69
+ if i == 1 {
70
+ iptBin = "ip6tables"
50
71
}
51
72
52
- var addJumpRule []string
53
- if firstRejectRuleNum > 0 {
54
- addJumpRule = append ([]string {"-t" , string (iptables .Filter ), "-I" , "INPUT" , strconv .Itoa (firstRejectRuleNum )},
55
- jumpRule ... )
56
- } else {
57
- addJumpRule = append ([]string {"-t" , string (iptables .Filter ), "-A" , "INPUT" }, jumpRule ... )
73
+ // Ensure UNCLOUD-INPUT chain exists. All existing rules are flushed.
74
+ if _ , err := ipt .NewChain (UncloudInputChain , iptables .Filter ); err != nil {
75
+ return fmt .Errorf ("create %s chain '%s': %w" , iptBin , UncloudInputChain , err )
58
76
}
59
- if err = ipt .RawCombinedOutput (addJumpRule ... ); err != nil {
60
- return fmt .Errorf ("add iptables rule '%s': %w" , strings . Join ( addJumpRule , " " ) , err )
77
+ if err : = ipt .RawCombinedOutput ("-t" , string ( iptables . Filter ), "-F" , UncloudInputChain ); err != nil {
78
+ return fmt .Errorf ("flush %s chain '%s': %w" , iptBin , UncloudInputChain , err )
61
79
}
62
- }
63
80
64
- // Allow WireGuard traffic to the machine.
65
- acceptWireGuardRule := []string {"-p" , "udp" , "--dport" , strconv .Itoa (network .WireGuardPort ), "-j" , "ACCEPT" }
66
- err := ipt .ProgramRule (iptables .Filter , UncloudInputChain , iptables .Insert , acceptWireGuardRule )
67
- if err != nil {
68
- return fmt .Errorf ("insert iptables rule '%s': %w" , strings .Join (acceptWireGuardRule , " " ), err )
81
+ // Ensure the main INPUT chain has a jump rule to the UNCLOUD-INPUT chain before any DROP/REJECT rules.
82
+ jumpRule := []string {"-m" , "comment" , "--comment" , "Uncloud-managed" , "-j" , UncloudInputChain }
83
+ if ! ipt .Exists (iptables .Filter , "INPUT" , jumpRule ... ) {
84
+ // Look for the first DROP/REJECT rule in the INPUT chain.
85
+ out , err := ipt .Raw ("-t" , string (iptables .Filter ), "-L" , "INPUT" , "--line-numbers" )
86
+ if err != nil {
87
+ return fmt .Errorf ("get %s rules for chain '%s': %w" , iptBin , UncloudInputChain , err )
88
+ }
89
+
90
+ firstRejectRuleNum := 0
91
+ for _ , line := range strings .Split (string (out ), "\n " ) {
92
+ fields := strings .Fields (line )
93
+ if len (fields ) < 2 {
94
+ continue
95
+ }
96
+ if fields [1 ] == "DROP" || fields [1 ] == "REJECT" {
97
+ if ruleNum , err := strconv .Atoi (fields [0 ]); err == nil {
98
+ firstRejectRuleNum = ruleNum
99
+ break
100
+ }
101
+ }
102
+ }
103
+
104
+ var addJumpRule []string
105
+ if firstRejectRuleNum > 0 {
106
+ addJumpRule = append ([]string {"-t" , string (iptables .Filter ), "-I" , "INPUT" ,
107
+ strconv .Itoa (firstRejectRuleNum )}, jumpRule ... )
108
+ } else {
109
+ addJumpRule = append ([]string {"-t" , string (iptables .Filter ), "-A" , "INPUT" }, jumpRule ... )
110
+ }
111
+ if err = ipt .RawCombinedOutput (addJumpRule ... ); err != nil {
112
+ return fmt .Errorf ("add %s rule '%s': %w" , iptBin , strings .Join (addJumpRule , " " ), err )
113
+ }
114
+ }
69
115
}
70
116
71
117
return nil
72
118
}
73
119
74
120
// CleanupIptablesChains removes the custom iptables chains and rules created by ConfigureIptablesChains.
75
121
func CleanupIptablesChains () error {
76
- ipt := iptables .GetIptable (iptables .IPv4 )
122
+ ipt4 := iptables .GetIptable (iptables .IPv4 )
123
+ ipt6 := iptables .GetIptable (iptables .IPv6 )
77
124
78
- // First, remove the jump rule from INPUT chain to UNCLOUD-INPUT.
79
- jumpRule := [] string { "-m" , "comment" , "--comment" , "Uncloud-managed" , "-j" , UncloudInputChain }
80
- if err := ipt . ProgramRule ( iptables . Filter , "INPUT" , iptables . Delete , jumpRule ); err != nil {
81
- return fmt . Errorf ( "delete iptables jump rule from INPUT: %w" , err )
82
- }
125
+ for i , ipt := range [] * iptables. IPTable { ipt4 , ipt6 } {
126
+ iptBin := "iptables"
127
+ if i == 1 {
128
+ iptBin = "ip6tables"
129
+ }
83
130
84
- // Flush all rules from UNCLOUD-INPUT chain as it must be empty before deletion.
85
- if err := ipt .RawCombinedOutput ("-t" , string (iptables .Filter ), "-F" , UncloudInputChain ); err != nil {
86
- // Chain might not exist which is fine.
87
- if ! strings .Contains (err .Error (), "No chain" ) {
88
- return fmt .Errorf ("flush iptables chain '%s': %w" , UncloudInputChain , err )
131
+ // First, remove the jump rule from INPUT chain to UNCLOUD-INPUT.
132
+ jumpRule := []string {"-m" , "comment" , "--comment" , "Uncloud-managed" , "-j" , UncloudInputChain }
133
+ if err := ipt .ProgramRule (iptables .Filter , "INPUT" , iptables .Delete , jumpRule ); err != nil {
134
+ return fmt .Errorf ("delete %s jump rule from INPUT: %w" , iptBin , err )
89
135
}
90
- }
91
136
92
- // Delete the UNCLOUD-INPUT chain.
93
- if err := ipt .RawCombinedOutput ("-t" , string (iptables .Filter ), "-X" , UncloudInputChain ); err != nil {
94
- // Chain might not exist which is fine.
95
- if ! strings .Contains (err .Error (), "No chain" ) {
96
- return fmt .Errorf ("delete iptables chain '%s': %w" , UncloudInputChain , err )
137
+ // Flush all rules from UNCLOUD-INPUT chain as it must be empty before deletion.
138
+ if err := ipt .RawCombinedOutput ("-t" , string (iptables .Filter ), "-F" , UncloudInputChain ); err != nil {
139
+ // Chain might not exist which is fine.
140
+ if ! strings .Contains (err .Error (), "No chain" ) {
141
+ return fmt .Errorf ("flush %s chain '%s': %w" , iptBin , UncloudInputChain , err )
142
+ }
143
+ }
144
+
145
+ // Delete the UNCLOUD-INPUT chain.
146
+ if err := ipt .RawCombinedOutput ("-t" , string (iptables .Filter ), "-X" , UncloudInputChain ); err != nil {
147
+ // Chain might not exist which is fine.
148
+ if ! strings .Contains (err .Error (), "No chain" ) {
149
+ return fmt .Errorf ("delete %s chain '%s': %w" , iptBin , UncloudInputChain , err )
150
+ }
151
+ } else {
152
+ slog .Info ("Deleted %s chain." , "chain" , iptBin , UncloudInputChain )
97
153
}
98
- } else {
99
- slog .Info ("Deleted iptables chain." , "chain" , UncloudInputChain )
100
154
}
101
155
102
156
return nil
0 commit comments