Skip to content

Commit

Permalink
* Add iptables4nattemplate chain client element to connectioncontextk…
Browse files Browse the repository at this point in the history
…ernel chain

* Turn routelocalnet chain element to a client element and move to cmnnectioncontextkernel chain

* Add setroutelocalnet chain server element

Signed-off-by: Sergey Shlyanin <sergey.shlyanin@xored.com>
  • Loading branch information
Sergey Shlyanin committed May 12, 2022
1 parent cc7b4d9 commit 9bd5e37
Show file tree
Hide file tree
Showing 9 changed files with 395 additions and 36 deletions.
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ module github.com/networkservicemesh/sdk-kernel
go 1.18

require (
github.com/edwarnicke/exechelper v1.0.2
github.com/golang/protobuf v1.5.2
github.com/networkservicemesh/api v1.3.2-0.20220509143420-a1414febd727
github.com/networkservicemesh/api v1.3.2-0.20220512163820-8c875d61945b
github.com/networkservicemesh/sdk v0.5.1-0.20220507173809-41196bdf49db
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0
Expand All @@ -22,6 +23,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.2.1 // indirect
github.com/go-logr/stdr v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edwarnicke/exechelper v1.0.2 h1:dD49Ui2U0FBFxxhalnKw6vLS0P0TkgnXBRvKL/xmC5w=
github.com/edwarnicke/exechelper v1.0.2/go.mod h1:/T271jtNX/ND4De6pa2aRy2+8sNtyCDB1A2pp4M+fUs=
github.com/edwarnicke/serialize v1.0.7 h1:geX8vmyu8Ij2S5fFIXjy9gBDkKxXnrMIzMoDvV0Ddac=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down Expand Up @@ -61,6 +63,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
Expand All @@ -70,8 +74,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/networkservicemesh/api v1.3.2-0.20220509143420-a1414febd727 h1:IonbJeVgkwPLOrvDjd+c5Q2QPxtAUrwdLfAUv+8qk4w=
github.com/networkservicemesh/api v1.3.2-0.20220509143420-a1414febd727/go.mod h1:hOF2844BSstH1311oDMDgqqXS+kdc77htZNPRKl9mf8=
github.com/networkservicemesh/api v1.3.2-0.20220512163820-8c875d61945b h1:suJRTlWU7/N0gF3FdcN9kCf1MO5Z7CdVSBdb2JTkLhk=
github.com/networkservicemesh/api v1.3.2-0.20220512163820-8c875d61945b/go.mod h1:hOF2844BSstH1311oDMDgqqXS+kdc77htZNPRKl9mf8=
github.com/networkservicemesh/sdk v0.5.1-0.20220507173809-41196bdf49db h1:Ux4NNmYfPm/ayaR1DD5AWMXGSkPm+PdGHbvu34TAAno=
github.com/networkservicemesh/sdk v0.5.1-0.20220507173809-41196bdf49db/go.mod h1:G+NdPbtzcOWx1VljOj+L4kvZPQyYpiwCp84JYs+hGtc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
4 changes: 4 additions & 0 deletions pkg/kernel/networkservice/connectioncontextkernel/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ package connectioncontextkernel
import (
"github.com/networkservicemesh/api/pkg/api/networkservice"

"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/connectioncontextkernel/iptables4nattemplate"
"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/connectioncontextkernel/mtu"
"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/connectioncontextkernel/routelocalnet"

"github.com/networkservicemesh/sdk/pkg/networkservice/core/chain"

Expand Down Expand Up @@ -62,5 +64,7 @@ func NewClient() networkservice.NetworkServiceClient {
ipneighbors.NewClient(),
routes.NewClient(),
ipaddress.NewClient(),
routelocalnet.NewClient(),
iptables4nattemplate.NewClient(),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) 2022 Xored Software Inc and others.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build linux
// +build linux

package iptables4nattemplate

import (
"context"

"github.com/pkg/errors"
"google.golang.org/grpc"

"github.com/golang/protobuf/ptypes/empty"
"github.com/networkservicemesh/api/pkg/api/networkservice"
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"

"github.com/networkservicemesh/sdk-kernel/pkg/kernel/tools/nshandle"
)

type iptablesClient struct {
manager IPTablesManager
}

// NewClient - returns a new networkservice.NetworkServiceClient that modify IPTables rules
// by mechanism provided template on Request and rollbacks rules changes on Close
func NewClient() networkservice.NetworkServiceClient {
return &iptablesClient{
manager: &iptableManagerImpl{},
}
}

func (c *iptablesClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) {
ctxMap := metadata.Map(ctx, metadata.IsClient(c))
_, rulesWasApplied := ctxMap.Load(applyIPTablesKey{})

conn, err := next.Client(ctx).Request(ctx, request, opts...)
if err != nil {
return nil, err
}

// Check refresh requests
if rulesWasApplied {
return conn, nil
}

mechanism := kernel.ToMechanism(conn.GetMechanism())
if mechanism != nil && len(mechanism.GetIPTables4NatTemplate()) != 0 {
rules, err := mechanism.EvaluateIPTables4NatTemplate(conn)
if err != nil {
return nil, err
}

currentNsHandler, err := nshandle.Current()
if err != nil {
return nil, err
}
defer func() { _ = currentNsHandler.Close() }()

targetHsHandler, err := nshandle.FromURL(mechanism.GetNetNSURL())
if err != nil {
return nil, err
}
defer func() { _ = targetHsHandler.Close() }()

err = nshandle.RunIn(currentNsHandler, targetHsHandler, func() error {
initialRules, iptableErr := c.manager.Get()
if iptableErr != nil {
return iptableErr
}

ctxMap.Store(applyIPTablesKey{}, initialRules)

iptableErr = c.manager.Apply(rules)
if iptableErr != nil {
return iptableErr
}

return nil
})

if err != nil {
return nil, err
}
}

return conn, nil
}

func (c *iptablesClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) {
_, err := next.Client(ctx).Close(ctx, conn, opts...)

var restoreErr error
ctxMap := metadata.Map(ctx, metadata.IsClient(c))
if initialRules, rulesWasApplied := ctxMap.Load(applyIPTablesKey{}); rulesWasApplied {
mechanism := kernel.ToMechanism(conn.GetMechanism())
currentNsHandler, handleErr := nshandle.Current()
if handleErr != nil {
return nil, handleErr
}
defer func() { _ = currentNsHandler.Close() }()

targetHsHandler, handleErr := nshandle.FromURL(mechanism.GetNetNSURL())
if handleErr != nil {
return nil, handleErr
}
defer func() { _ = targetHsHandler.Close() }()

restoreErr = nshandle.RunIn(currentNsHandler, targetHsHandler, func() error {
return c.manager.Restore(initialRules.(string))
})
}

if err != nil && restoreErr != nil {
return nil, errors.Wrap(err, restoreErr.Error())
}
if restoreErr != nil {
return nil, restoreErr
}

return &empty.Empty{}, err
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) 2022 Xored Software Inc and others.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build linux
// +build linux

package iptables4nattemplate

import (
"bytes"
"fmt"
"os"
"strings"

"github.com/edwarnicke/exechelper"
"github.com/pkg/errors"
)

type applyIPTablesKey struct {
}

type iptableManagerImpl struct {
}

// IPTablesManager provides methods for iptables nat rules management
type IPTablesManager interface {
Get() (string, error)
Restore(string) error
Apply([]string) error
}

func (m *iptableManagerImpl) Get() (string, error) {
cmdStr := "iptables-save"
buf := bytes.NewBuffer([]byte{})
err := exechelper.Run(cmdStr,
exechelper.WithStdout(buf),
exechelper.WithStderr(buf),
)
if err != nil {
err = errors.Wrapf(err, "%s", buf.String())
return "", err
}

return buf.String(), nil
}

func (m *iptableManagerImpl) Apply(rules []string) error {
for _, rule := range rules {
arguments := strings.Split(rule, " ")

cmdStr := "iptables -t nat"
buf := bytes.NewBuffer([]byte{})
err := exechelper.Run(cmdStr,
exechelper.WithArgs(arguments...),
exechelper.WithStdout(buf),
exechelper.WithStderr(buf),
)
if err != nil {
err = errors.Wrapf(err, "%s", buf.String())
return err
}
}

return nil
}

func (m *iptableManagerImpl) writeTmpRule(rules string) (string, error) {
fo, err := os.CreateTemp("/tmp", "rules-*")
if err != nil {
return "", err
}

defer func() { _ = fo.Close() }()
_, err = fo.WriteString(rules)
if err != nil {
return "", err
}

return fo.Name(), nil
}

func (m *iptableManagerImpl) Restore(rules string) error {
// Save rules to a temp file
tmpFile, err := m.writeTmpRule(rules)
if err != nil {
return err
}

defer func() { _ = os.Remove(tmpFile) }()

// Restore rules
cmdStr := fmt.Sprintf("iptables-restore %s", tmpFile)
buf := bytes.NewBuffer([]byte{})
err = exechelper.Run(cmdStr,
exechelper.WithStdout(buf),
exechelper.WithStderr(buf),
)
if err != nil {
err = errors.Wrapf(err, "%s", buf.String())
return err
}

return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2022 Xored Software Inc and others.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package iptables4nattemplate provides chain element for setup iptables nat rules
package iptables4nattemplate
Loading

0 comments on commit 9bd5e37

Please sign in to comment.