diff --git a/.github/workflows/android-build-validation.yml b/.github/workflows/android-build-validation.yml index 6a0e6f3d9..7dbe82308 100644 --- a/.github/workflows/android-build-validation.yml +++ b/.github/workflows/android-build-validation.yml @@ -22,6 +22,13 @@ jobs: go-version: "1.21.x" - name: Setup Android SDK uses: android-actions/setup-android@v2 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + java-version: "8" + distribution: "adopt" + - name: NDK Cache id: ndk-cache uses: actions/cache@v3 @@ -38,4 +45,4 @@ jobs: run: PATH=$PATH:$(go env GOPATH) gomobile bind -o $GITHUB_WORKSPACE/netbird.aar -javapkg=io.netbird.gomobile -ldflags="-X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/io.netbird.client/cache/wireguard -X github.com/netbirdio/netbird/version.version=buildtest" $GITHUB_WORKSPACE/client/android env: CGO_ENABLED: 0 - ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk/23.1.7779620 \ No newline at end of file + ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk/23.1.7779620 diff --git a/client/firewall/nftables/acl_linux.go b/client/firewall/nftables/acl_linux.go index d15d68345..1fa41b63a 100644 --- a/client/firewall/nftables/acl_linux.go +++ b/client/firewall/nftables/acl_linux.go @@ -58,6 +58,7 @@ type AclManager struct { type iFaceMapper interface { Name() string Address() iface.WGAddress + IsUserspaceBind() bool } func newAclManager(table *nftables.Table, wgIface iFaceMapper, routeingFwChainName string) (*AclManager, error) { @@ -198,6 +199,81 @@ func (m *AclManager) DeleteRule(rule firewall.Rule) error { return nil } +// createDefaultAllowRules In case if the USP firewall manager can use the native firewall manager we must to create allow rules for +// input and output chains +func (m *AclManager) createDefaultAllowRules() error { + expIn := []expr.Any{ + &expr.Payload{ + DestRegister: 1, + Base: expr.PayloadBaseNetworkHeader, + Offset: 12, + Len: 4, + }, + // mask + &expr.Bitwise{ + SourceRegister: 1, + DestRegister: 1, + Len: 4, + Mask: []byte{0x00, 0x00, 0x00, 0x00}, + Xor: zeroXor, + }, + // net address + &expr.Cmp{ + Register: 1, + Data: []byte{0x00, 0x00, 0x00, 0x00}, + }, + &expr.Verdict{ + Kind: expr.VerdictAccept, + }, + } + + _ = m.rConn.InsertRule(&nftables.Rule{ + Table: m.workTable, + Chain: m.chainInputRules, + Position: 0, + Exprs: expIn, + }) + + expOut := []expr.Any{ + &expr.Payload{ + DestRegister: 1, + Base: expr.PayloadBaseNetworkHeader, + Offset: 16, + Len: 4, + }, + // mask + &expr.Bitwise{ + SourceRegister: 1, + DestRegister: 1, + Len: 4, + Mask: []byte{0x00, 0x00, 0x00, 0x00}, + Xor: zeroXor, + }, + // net address + &expr.Cmp{ + Register: 1, + Data: []byte{0x00, 0x00, 0x00, 0x00}, + }, + &expr.Verdict{ + Kind: expr.VerdictAccept, + }, + } + + _ = m.rConn.InsertRule(&nftables.Rule{ + Table: m.workTable, + Chain: m.chainOutputRules, + Position: 0, + Exprs: expOut, + }) + + err := m.rConn.Flush() + if err != nil { + log.Debugf("failed to create default allow rules: %s", err) + return err + } + return nil +} + // Flush rule/chain/set operations from the buffer // // Method also get all rules after flush and refreshes handle values in the rulesets diff --git a/client/firewall/nftables/manager_linux.go b/client/firewall/nftables/manager_linux.go index fad2d7804..8395fc270 100644 --- a/client/firewall/nftables/manager_linux.go +++ b/client/firewall/nftables/manager_linux.go @@ -106,11 +106,19 @@ func (m *Manager) RemoveRoutingRules(pair firewall.RouterPair) error { } // AllowNetbird allows netbird interface traffic -// todo review this method usage func (m *Manager) AllowNetbird() error { + if !m.wgIface.IsUserspaceBind() { + return nil + } + m.mutex.Lock() defer m.mutex.Unlock() + err := m.aclManager.createDefaultAllowRules() + if err != nil { + return fmt.Errorf("failed to create default allow rules: %v", err) + } + chains, err := m.rConn.ListChainsOfTableFamily(nftables.TableFamilyIPv4) if err != nil { return fmt.Errorf("list of chains: %w", err) @@ -145,6 +153,7 @@ func (m *Manager) AllowNetbird() error { if err != nil { return fmt.Errorf("failed to flush allow input netbird rules: %v", err) } + return nil } diff --git a/client/firewall/nftables/manager_linux_test.go b/client/firewall/nftables/manager_linux_test.go index 74ddaf6e1..1f226e315 100644 --- a/client/firewall/nftables/manager_linux_test.go +++ b/client/firewall/nftables/manager_linux_test.go @@ -37,6 +37,8 @@ func (i *iFaceMock) Address() iface.WGAddress { panic("AddressFunc is not set") } +func (i *iFaceMock) IsUserspaceBind() bool { return false } + func TestNftablesManager(t *testing.T) { mock := &iFaceMock{ NameFunc: func() string { diff --git a/client/internal/acl/manager_test.go b/client/internal/acl/manager_test.go index 5e3db0a24..494d54bf2 100644 --- a/client/internal/acl/manager_test.go +++ b/client/internal/acl/manager_test.go @@ -38,7 +38,7 @@ func TestDefaultManager(t *testing.T) { defer ctrl.Finish() ifaceMock := mocks.NewMockIFaceMapper(ctrl) - ifaceMock.EXPECT().IsUserspaceBind().Return(true) + ifaceMock.EXPECT().IsUserspaceBind().Return(true).AnyTimes() ifaceMock.EXPECT().SetFilter(gomock.Any()) ip, network, err := net.ParseCIDR("172.0.0.1/32") if err != nil { @@ -331,7 +331,7 @@ func TestDefaultManagerEnableSSHRules(t *testing.T) { defer ctrl.Finish() ifaceMock := mocks.NewMockIFaceMapper(ctrl) - ifaceMock.EXPECT().IsUserspaceBind().Return(true) + ifaceMock.EXPECT().IsUserspaceBind().Return(true).AnyTimes() ifaceMock.EXPECT().SetFilter(gomock.Any()) ip, network, err := net.ParseCIDR("172.0.0.1/32") if err != nil { diff --git a/iface/tun_usp_linux.go b/iface/tun_usp_linux.go index 3ed518d52..f516b9f4d 100644 --- a/iface/tun_usp_linux.go +++ b/iface/tun_usp_linux.go @@ -45,6 +45,7 @@ func (t *tunUSPDevice) Create() (wgConfigurer, error) { log.Info("create tun interface") tunIface, err := tun.CreateTUN(t.name, t.mtu) if err != nil { + log.Debugf("faile to create tun unterface (%s, %d): %s", t.name, t.mtu, err) return nil, err } t.wrapper = newDeviceWrapper(tunIface)