Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix allow netbird traffic for nftables and userspace #1446

Merged
merged 12 commits into from
Jan 11, 2024
9 changes: 8 additions & 1 deletion .github/workflows/android-build-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
ANDROID_NDK_HOME: /usr/local/lib/android/sdk/ndk/23.1.7779620
76 changes: 76 additions & 0 deletions client/firewall/nftables/acl_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions client/firewall/nftables/manager_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,11 @@ 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()

Expand Down Expand Up @@ -145,7 +148,8 @@ func (m *Manager) AllowNetbird() error {
if err != nil {
return fmt.Errorf("failed to flush allow input netbird rules: %v", err)
}
return nil

return m.aclManager.createDefaultAllowRules()
}

// Reset firewall to the default state
Expand Down
2 changes: 2 additions & 0 deletions client/firewall/nftables/manager_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions client/internal/acl/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions iface/tun_usp_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
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)

Check failure on line 48 in iface/tun_usp_linux.go

View workflow job for this annotation

GitHub Actions / codespell

faile ==> fail, failed
return nil, err
}
t.wrapper = newDeviceWrapper(tunIface)
Expand Down
Loading