Skip to content

Commit 6111213

Browse files
committed
refactor: split allow/deny lists to also preceeding ones
1 parent 1d4ecd2 commit 6111213

File tree

7 files changed

+148
-289
lines changed

7 files changed

+148
-289
lines changed

packages/api/internal/handlers/sandbox_create.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"github.com/e2b-dev/infra/packages/db/types"
2424
"github.com/e2b-dev/infra/packages/shared/pkg/id"
2525
sbxlogger "github.com/e2b-dev/infra/packages/shared/pkg/logger/sandbox"
26-
sandbox_network "github.com/e2b-dev/infra/packages/shared/pkg/sandbox-network"
2726
"github.com/e2b-dev/infra/packages/shared/pkg/telemetry"
2827
sharedUtils "github.com/e2b-dev/infra/packages/shared/pkg/utils"
2928
)
@@ -296,19 +295,6 @@ func validateNetworkConfig(network *api.SandboxNetworkConfig) *api.APIError {
296295
return nil
297296
}
298297

299-
if network.AllowOut != nil {
300-
for _, address := range *network.AllowOut {
301-
cidr := sandbox_network.AddressStringToCIDR(address)
302-
if err := sandbox_network.CanAllowCIDR(cidr); err != nil {
303-
return &api.APIError{
304-
Code: http.StatusBadRequest,
305-
Err: fmt.Errorf("invalid allowOut CIDR (%s): %w", cidr, err),
306-
ClientMsg: fmt.Sprintf("address is not allowed for allowOut: %s", address),
307-
}
308-
}
309-
}
310-
}
311-
312298
if maskRequestHost := network.MaskRequestHost; maskRequestHost != nil {
313299
hostname, _, err := splitHostPortOptional(*maskRequestHost)
314300
if err != nil {

packages/api/internal/orchestrator/create_instance.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"errors"
66
"fmt"
77
"net/http"
8-
"slices"
98
"time"
109

1110
"go.opentelemetry.io/otel/attribute"
@@ -30,8 +29,7 @@ import (
3029
)
3130

3231
// buildNetworkConfig constructs the orchestrator network configuration from the input parameters
33-
func buildNetworkConfig(network *types.SandboxNetworkConfig, allowInternetAccess *bool, trafficAccessToken *string) (n *orchestrator.SandboxNetworkConfig, aia *bool) {
34-
aia = allowInternetAccess
32+
func buildNetworkConfig(network *types.SandboxNetworkConfig, allowInternetAccess *bool, trafficAccessToken *string) *orchestrator.SandboxNetworkConfig {
3533
orchNetwork := &orchestrator.SandboxNetworkConfig{
3634
Egress: &orchestrator.SandboxNetworkEgressConfig{},
3735
Ingress: &orchestrator.SandboxNetworkIngressConfig{
@@ -56,15 +54,7 @@ func buildNetworkConfig(network *types.SandboxNetworkConfig, allowInternetAccess
5654
orchNetwork.Egress.DeniedCidrs = []string{sandbox_network.AllInternetTrafficCIDR}
5755
}
5856

59-
if slices.Contains(orchNetwork.GetEgress().GetAllowedCidrs(), sandbox_network.AllInternetTrafficCIDR) {
60-
// If all traffic is allowed, clear the allowed and denied lists
61-
// Internet access is enabled by default.
62-
orchNetwork.Egress.AllowedCidrs = nil
63-
orchNetwork.Egress.DeniedCidrs = nil
64-
aia = ut.ToPtr(true)
65-
}
66-
67-
return orchNetwork, aia
57+
return orchNetwork
6858
}
6959

7060
func (o *Orchestrator) CreateSandbox(
@@ -194,7 +184,7 @@ func (o *Orchestrator) CreateSandbox(
194184
trafficAccessToken = &accessToken
195185
}
196186

197-
sbxNetwork, allowInternetAccess := buildNetworkConfig(network, allowInternetAccess, trafficAccessToken)
187+
sbxNetwork := buildNetworkConfig(network, allowInternetAccess, trafficAccessToken)
198188
sbxRequest := &orchestrator.SandboxCreateRequest{
199189
Sandbox: &orchestrator.SandboxConfig{
200190
BaseTemplateId: baseTemplateID,

packages/orchestrator/internal/sandbox/network/firewall.go

Lines changed: 126 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ type Firewall struct {
2222
table *nftables.Table
2323
chain *nftables.Chain
2424

25-
blockInternetTraffic bool
26-
denySet set.Set
27-
allowSet set.Set
28-
tapInterface string
25+
predefinedDenySet set.Set
26+
predefinedAllowSet set.Set
27+
28+
userDenySet set.Set
29+
userAllowSet set.Set
30+
31+
tapInterface string
2932

3033
allowedRanges []string
3134
}
@@ -51,6 +54,15 @@ func NewFirewall(tapIf string, hyperloopIP string) (*Firewall, error) {
5154
})
5255

5356
// Create deny-set and allow-set
57+
alwaysDenySet, err := set.New(conn, table, "filtered_always_denylist", nftables.TypeIPAddr)
58+
if err != nil {
59+
return nil, fmt.Errorf("new deny set: %w", err)
60+
}
61+
alwaysAllowSet, err := set.New(conn, table, "filtered_always_allowlist", nftables.TypeIPAddr)
62+
if err != nil {
63+
return nil, fmt.Errorf("new allow set: %w", err)
64+
}
65+
5466
denySet, err := set.New(conn, table, "filtered_denylist", nftables.TypeIPAddr)
5567
if err != nil {
5668
return nil, fmt.Errorf("new deny set: %w", err)
@@ -61,14 +73,15 @@ func NewFirewall(tapIf string, hyperloopIP string) (*Firewall, error) {
6173
}
6274

6375
fw := &Firewall{
64-
conn: conn,
65-
table: table,
66-
chain: chain,
67-
blockInternetTraffic: false,
68-
denySet: denySet,
69-
allowSet: allowSet,
70-
tapInterface: tapIf,
71-
allowedRanges: []string{fmt.Sprintf("%s/32", hyperloopIP)},
76+
conn: conn,
77+
table: table,
78+
chain: chain,
79+
predefinedDenySet: alwaysDenySet,
80+
predefinedAllowSet: alwaysAllowSet,
81+
userDenySet: denySet,
82+
userAllowSet: allowSet,
83+
tapInterface: tapIf,
84+
allowedRanges: []string{fmt.Sprintf("%s/32", hyperloopIP)},
7285
}
7386

7487
// Add firewall rules to the chain
@@ -77,9 +90,9 @@ func NewFirewall(tapIf string, hyperloopIP string) (*Firewall, error) {
7790
}
7891

7992
// Populate the sets with initial data
80-
err = fw.ResetAllCustom()
93+
err = fw.ResetAllSets()
8194
if err != nil {
82-
return nil, fmt.Errorf("error while configuring initial deny set: %w", err)
95+
return nil, fmt.Errorf("error while configuring initial data: %w", err)
8396
}
8497

8598
return fw, nil
@@ -119,26 +132,52 @@ func (fw *Firewall) installRules() error {
119132
),
120133
})
121134

122-
// Allow anything in allowSet
135+
// The order should be
136+
// 1. Allow anything in predefinedAllowSet
137+
// 2. Deny anything in predefinedDenySet
138+
// 3. Allow anything in userAllowSet
139+
// 4. Deny anything in userDenySet
140+
141+
// Allow anything in userAllowSet
123142
fw.conn.InsertRule(&nftables.Rule{
124143
Table: fw.table, Chain: fw.chain,
125144
Exprs: append(ifaceMatch,
126145
expressions.IPv4DestinationAddress(1),
127-
expressions.IPSetLookUp(fw.allowSet.Set(), 1),
146+
expressions.IPSetLookUp(fw.userAllowSet.Set(), 1),
128147
expressions.Accept(),
129148
),
130149
})
131150

132-
// Drop anything in denySet
151+
// Drop anything in userDenySet
133152
fw.conn.AddRule(&nftables.Rule{
134153
Table: fw.table, Chain: fw.chain,
135154
Exprs: append(ifaceMatch,
136155
expressions.IPv4DestinationAddress(1),
137-
expressions.IPSetLookUp(fw.denySet.Set(), 1),
156+
expressions.IPSetLookUp(fw.userDenySet.Set(), 1),
138157
expressions.Drop(),
139158
),
140159
})
141160

161+
// Drop anything in predefinedDenySet
162+
fw.conn.InsertRule(&nftables.Rule{
163+
Table: fw.table, Chain: fw.chain,
164+
Exprs: append(ifaceMatch,
165+
expressions.IPv4DestinationAddress(1),
166+
expressions.IPSetLookUp(fw.predefinedDenySet.Set(), 1),
167+
expressions.Drop(),
168+
),
169+
})
170+
171+
// Accept anything in predefinedAllowSet
172+
fw.conn.InsertRule(&nftables.Rule{
173+
Table: fw.table, Chain: fw.chain,
174+
Exprs: append(ifaceMatch,
175+
expressions.IPv4DestinationAddress(1),
176+
expressions.IPSetLookUp(fw.predefinedAllowSet.Set(), 1),
177+
expressions.Accept(),
178+
),
179+
})
180+
142181
if err := fw.conn.Flush(); err != nil {
143182
return fmt.Errorf("flush nftables changes: %w", err)
144183
}
@@ -148,118 +187,117 @@ func (fw *Firewall) installRules() error {
148187

149188
// AddDeniedCIDR adds a single CIDR to the deny set at runtime.
150189
func (fw *Firewall) AddDeniedCIDR(cidr string) error {
151-
if fw.blockInternetTraffic {
152-
// If internet is denied, we don't need to add any other addresses to the deny set.
153-
// Because 0.0.0.0/0 is not valid IP per GoLang, we can't add new addresses to the deny set.
154-
return nil
155-
}
156-
157-
// 0.0.0.0/0 is not valid IP per GoLang, so we handle it as a special case
158-
if cidr == sandbox_network.AllInternetTrafficCIDR {
159-
fw.blockInternetTraffic = true
160-
161-
fw.conn.FlushSet(fw.denySet.Set())
162-
163-
toAppend := []nftables.SetElement{
164-
{Key: netip.MustParseAddr("0.0.0.0").AsSlice()},
165-
{
166-
Key: netip.MustParseAddr("255.255.255.255").AsSlice(),
167-
IntervalEnd: true,
168-
},
169-
}
170-
171-
if err := fw.conn.SetAddElements(fw.denySet.Set(), toAppend); err != nil {
172-
return fmt.Errorf("add elements to denied set: %w", err)
173-
}
174-
} else {
175-
current, err := fw.denySet.Elements(fw.conn)
176-
if err != nil {
177-
return err
178-
}
179-
180-
data, err := set.AddressStringsToSetData([]string{cidr})
181-
if err != nil {
182-
return err
183-
}
184-
merged := append(current, data...)
185-
if err := fw.denySet.ClearAndAddElements(fw.conn, merged); err != nil {
186-
return err
187-
}
190+
err := addCIDRToSet(fw.conn, fw.userDenySet, cidr)
191+
if err != nil {
192+
return fmt.Errorf("add denied CIDR to set: %w", err)
188193
}
189194

190-
err := fw.conn.Flush()
195+
err = fw.conn.Flush()
191196
if err != nil {
192-
return fmt.Errorf("flush add denied cidr changes: %w", err)
197+
return fmt.Errorf("flush add denied changes: %w", err)
193198
}
194199

195200
return nil
196201
}
197202

198203
// AddAllowedCIDR adds a single CIDR to the allow set at runtime.
199204
func (fw *Firewall) AddAllowedCIDR(cidr string) error {
200-
err := sandbox_network.CanAllowCIDR(cidr)
205+
err := addCIDRToSet(fw.conn, fw.userAllowSet, cidr)
201206
if err != nil {
202-
return err
203-
}
204-
205-
data, err := set.AddressStringsToSetData([]string{cidr})
206-
if err != nil {
207-
return err
208-
}
209-
current, err := fw.allowSet.Elements(fw.conn)
210-
if err != nil {
211-
return err
212-
}
213-
merged := append(current, data...)
214-
if err := fw.allowSet.ClearAndAddElements(fw.conn, merged); err != nil {
215-
return err
207+
return fmt.Errorf("add allowed CIDR to set: %w", err)
216208
}
217209

218210
err = fw.conn.Flush()
219211
if err != nil {
220-
return fmt.Errorf("flush add allowed IP changes: %w", err)
212+
return fmt.Errorf("flush add allowed changes: %w", err)
221213
}
222214

223215
return nil
224216
}
225217

226-
func (fw *Firewall) ResetAllCustom() error {
227-
if err := fw.ResetDeniedCustom(); err != nil {
228-
return fmt.Errorf("clear block set: %w", err)
218+
func (fw *Firewall) ResetAllSets() error {
219+
if err := fw.ResetDeniedSets(); err != nil {
220+
return fmt.Errorf("clear denied set: %w", err)
229221
}
230-
if err := fw.ResetAllowedCustom(); err != nil {
222+
if err := fw.ResetAllowedSets(); err != nil {
231223
return fmt.Errorf("clear allow set: %w", err)
232224
}
233225

234226
return nil
235227
}
236228

237-
// ResetDeniedCustom resets the deny set back to original ranges.
238-
func (fw *Firewall) ResetDeniedCustom() error {
239-
initData, err := set.AddressStringsToSetData(sandbox_network.DeniedSandboxCIDRs)
240-
if err != nil {
241-
return fmt.Errorf("parse initial denied CIDRs: %w", err)
229+
// ResetDeniedSets resets the deny set back to original ranges.
230+
func (fw *Firewall) ResetDeniedSets() error {
231+
// Always deny the default ranges
232+
if err := fw.predefinedDenySet.ClearAndAddElements(fw.conn, sandbox_network.DeniedSandboxSetData); err != nil {
233+
return err
242234
}
243235

244-
if err := fw.denySet.ClearAndAddElements(fw.conn, initData); err != nil {
236+
// User defined denied ranges
237+
if err := fw.userDenySet.ClearAndAddElements(fw.conn, nil); err != nil {
245238
return err
246239
}
247240

248-
fw.blockInternetTraffic = false
249-
250241
return fw.conn.Flush()
251242
}
252243

253-
// ResetAllowedCustom resets allow set back to original ranges.
254-
func (fw *Firewall) ResetAllowedCustom() error {
244+
// ResetAllowedSets resets allow set back to original ranges.
245+
func (fw *Firewall) ResetAllowedSets() error {
246+
// Always allowed ranges
255247
initData, err := set.AddressStringsToSetData(fw.allowedRanges)
256248
if err != nil {
257249
return fmt.Errorf("parse initial allowed CIDRs: %w", err)
258250
}
251+
if err := fw.predefinedAllowSet.ClearAndAddElements(fw.conn, initData); err != nil {
252+
return err
253+
}
259254

260-
if err := fw.allowSet.ClearAndAddElements(fw.conn, initData); err != nil {
255+
// User defined allowed ranges
256+
if err := fw.userAllowSet.ClearAndAddElements(fw.conn, nil); err != nil {
261257
return err
262258
}
263259

264260
return fw.conn.Flush()
265261
}
262+
263+
func addCIDRToSet(conn *nftables.Conn, ipset set.Set, cidr string) error {
264+
current, err := ipset.Elements(conn)
265+
if err != nil {
266+
return err
267+
}
268+
269+
if len(current) == 1 && current[0].AddressRangeStart == netip.MustParseAddr("0.0.0.0") && current[0].AddressRangeEnd == netip.MustParseAddr("255.255.255.255") {
270+
// Because 0.0.0.0/0 is not valid IP per GoLang, we can't add new addresses to the set.
271+
return nil
272+
}
273+
274+
// 0.0.0.0/0 is not valid IP per GoLang, so we handle it as a special case
275+
if cidr == sandbox_network.AllInternetTrafficCIDR {
276+
conn.FlushSet(ipset.Set())
277+
278+
toAppend := []nftables.SetElement{
279+
{
280+
Key: netip.MustParseAddr("0.0.0.0").AsSlice(),
281+
},
282+
{
283+
Key: netip.MustParseAddr("255.255.255.255").AsSlice(),
284+
IntervalEnd: true,
285+
},
286+
}
287+
288+
if err := conn.SetAddElements(ipset.Set(), toAppend); err != nil {
289+
return fmt.Errorf("add elements to denied set: %w", err)
290+
}
291+
292+
return nil
293+
}
294+
295+
data, err := set.AddressStringsToSetData([]string{cidr})
296+
if err != nil {
297+
return err
298+
}
299+
300+
merged := append(current, data...)
301+
302+
return ipset.ClearAndAddElements(conn, merged)
303+
}

packages/orchestrator/internal/sandbox/network/slot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func (s *Slot) ResetInternet(ctx context.Context) error {
309309
defer n.Close()
310310

311311
err = n.Do(func(_ ns.NetNS) error {
312-
err := s.Firewall.ResetAllCustom()
312+
err := s.Firewall.ResetAllSets()
313313
if err != nil {
314314
return fmt.Errorf("error cleaning firewall rules: %w", err)
315315
}

0 commit comments

Comments
 (0)