Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions v1/networking_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"net"
"net/http"
"regexp"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -188,8 +190,8 @@ func ValidateDockerFirewallAllowsEgress(ctx context.Context, client CloudInstanc
if err != nil {
return fmt.Errorf("failed to connect to Google's DNS server: %w, stderr: %s", err, stderr)
}
if !strings.Contains(stdout, "3 packets transmitted, 3 packets received") {
return fmt.Errorf("expected successful ping, got: %s", stdout)
if !dockerEgressPingReceivedReply(stdout) {
return fmt.Errorf("expected at least one successful ping reply, got: %s", stdout)
}

return nil
Expand Down Expand Up @@ -464,6 +466,21 @@ func runMicroK8sPodToPodTest(ctx context.Context, sshClient *ssh.Client, microK8
return nil
}

var pingStatsRe = regexp.MustCompile(`(?m)(\d+)\s+packets transmitted,\s+(\d+)\s+(?:packets\s+)?received`)

func dockerEgressPingReceivedReply(stdout string) bool {
matches := pingStatsRe.FindStringSubmatch(stdout)
if len(matches) != 3 {
return false
}

received, err := strconv.Atoi(matches[2])
if err != nil {
return false
}
return received > 0
}

// setupDockerCommand ensures Docker is available and returns the command to use (always with sudo)
func setupDockerCommand(ctx context.Context, sshClient *ssh.Client, instanceID CloudProviderInstanceID) (string, error) {
// Check if Docker is available
Expand Down
58 changes: 58 additions & 0 deletions v1/networking_validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package v1

import "testing"

func TestDockerEgressPingReceivedReply(t *testing.T) {
tests := []struct {
name string
out string
want bool
}{
{
name: "all packets received",
out: `PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=117 time=41.193 ms
64 bytes from 8.8.8.8: seq=1 ttl=117 time=41.023 ms
64 bytes from 8.8.8.8: seq=2 ttl=117 time=41.023 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss`,
want: true,
},
{
name: "partial packet loss still proves egress",
out: `PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=117 time=41.193 ms
64 bytes from 8.8.8.8: seq=2 ttl=117 time=41.023 ms
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 2 packets received, 33% packet loss`,
want: true,
},
{
name: "iputils ping format",
out: `--- 8.8.8.8 ping statistics ---
3 packets transmitted, 1 received, 66% packet loss, time 2003ms`,
want: true,
},
{
name: "no replies",
out: `--- 8.8.8.8 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss`,
want: false,
},
{
name: "no parseable stats",
out: `ping failed`,
want: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := dockerEgressPingReceivedReply(tt.out); got != tt.want {
t.Fatalf("dockerEgressPingReceivedReply() = %v, want %v", got, tt.want)
}
})
}
}
3 changes: 2 additions & 1 deletion v1/providers/nebius/scripts/brev-apply-docker-firewall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ iptables -A DOCKER-USER -i docker0 -o docker0 -j ACCEPT
iptables -A DOCKER-USER -i br+ -o br+ -j ACCEPT
iptables -A DOCKER-USER -i cni+ -o cni+ -j ACCEPT
iptables -A DOCKER-USER -i cali+ -o cali+ -j ACCEPT
iptables -A DOCKER-USER -i lo -j ACCEPT
iptables -A DOCKER-USER -i lo -j ACCEPT
iptables -A DOCKER-USER -i wt0 -j ACCEPT
iptables -A DOCKER-USER -j DROP
iptables -A DOCKER-USER -j RETURN

Expand Down
4 changes: 4 additions & 0 deletions v1/providers/shadeform/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ const (
// Allow inbound traffic on the loopback interface.
ipTablesAllowDockerUserInpboundLoopback = "iptables -A DOCKER-USER -i lo -j ACCEPT"

// Allow inbound traffic on the netbird interface.
ipTablesAllowDockerUserInpboundNetbird = "iptables -A DOCKER-USER -i wt0 -j ACCEPT"

// Allow external inbound TCP traffic to any container port 22 (SSH)
ipTablesAllowDockerUserContainerSSH = "iptables -A DOCKER-USER -p tcp --dport 22 -j ACCEPT"

Expand Down Expand Up @@ -99,6 +102,7 @@ func (c *ShadeformClient) getIPTablesCommands() []string {
ipTablesAllowDockerUserDockerToDocker2,
ipTablesAllowDockerUserDockerToDocker3,
ipTablesAllowDockerUserInpboundLoopback,
ipTablesAllowDockerUserInpboundNetbird,
ipTablesAllowDockerUserContainerSSH,
ipTablesDropDockerUserInbound,
ipTablesReturnDockerUser, // Expected by Docker
Expand Down
Loading