Skip to content

Commit

Permalink
Add IPSec mechanism
Browse files Browse the repository at this point in the history
Signed-off-by: Artem Glazychev <artem.glazychev@xored.com>
  • Loading branch information
glazychev-art committed Dec 6, 2022
1 parent 6668f53 commit ae72c6f
Show file tree
Hide file tree
Showing 22 changed files with 1,548 additions and 47 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ go 1.18

require (
git.fd.io/govpp.git v0.3.6-0.20210927044411-385ccc0d8ba9
github.com/edwarnicke/govpp v0.0.0-20221023154218-ef9a6adf6930
github.com/edwarnicke/govpp v0.0.0-20221205183833-306afd06cce5
github.com/edwarnicke/serialize v1.0.7
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.2.0
github.com/hashicorp/go-multierror v1.1.1
github.com/networkservicemesh/api v1.6.2-0.20221123101008-30ff0ca88ee8
github.com/networkservicemesh/api v1.6.2-0.20221205183940-84c7ff837cdd
github.com/networkservicemesh/sdk v0.5.1-0.20221205080356-9b1b773fbe13
github.com/networkservicemesh/sdk-kernel v0.0.0-20221205081316-4df325defbcc
github.com/pkg/errors v0.9.1
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
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/govpp v0.0.0-20221023154218-ef9a6adf6930 h1:/gS3gW7jV6ljzWcnHGxu1Yn1guxtwq8IuwJpK5TUl1w=
github.com/edwarnicke/govpp v0.0.0-20221023154218-ef9a6adf6930/go.mod h1:kHDnxA+SSNFeMEHz7xvhub1zvx4mOTRlWWRCay2n5NM=
github.com/edwarnicke/govpp v0.0.0-20221205183833-306afd06cce5 h1:8EvgVD6lkOjoVQuKY3/iQV3ewu+uIqu8TZaAsvkJPIs=
github.com/edwarnicke/govpp v0.0.0-20221205183833-306afd06cce5/go.mod h1:kHDnxA+SSNFeMEHz7xvhub1zvx4mOTRlWWRCay2n5NM=
github.com/edwarnicke/grpcfd v1.1.2 h1:2b8kCABQ1+JjSKGDoHadqSW7whCeTXMqtyo6jmB5B8k=
github.com/edwarnicke/grpcfd v1.1.2/go.mod h1:rHihB9YvNMixz8rS+ZbwosI2kj65VLkeyYAI2M+/cGA=
github.com/edwarnicke/serialize v0.0.0-20200705214914-ebc43080eecf/go.mod h1:XvbCO/QGsl3X8RzjBMoRpkm54FIAZH5ChK2j+aox7pw=
Expand Down Expand Up @@ -211,8 +211,8 @@ github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqc
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
github.com/networkservicemesh/api v1.6.2-0.20221123101008-30ff0ca88ee8 h1:243pLMg7+XD/794gnMlHRePyzxJJwECT+Gg9nAuiwTo=
github.com/networkservicemesh/api v1.6.2-0.20221123101008-30ff0ca88ee8/go.mod h1:hOF2844BSstH1311oDMDgqqXS+kdc77htZNPRKl9mf8=
github.com/networkservicemesh/api v1.6.2-0.20221205183940-84c7ff837cdd h1:26HR90HrJFZHIPPP3SCLGNRpPCMFoEnSSZfhHH8MPSo=
github.com/networkservicemesh/api v1.6.2-0.20221205183940-84c7ff837cdd/go.mod h1:hOF2844BSstH1311oDMDgqqXS+kdc77htZNPRKl9mf8=
github.com/networkservicemesh/sdk v0.5.1-0.20221205080356-9b1b773fbe13 h1:3iLQtkr1VoEwzDK2LemlTDtIGe8nyroDKD86FOtreYc=
github.com/networkservicemesh/sdk v0.5.1-0.20221205080356-9b1b773fbe13/go.mod h1:KlA3LQ3lLDnV9Y1C3jOTX3GeOXdmk2oL6oPYz2slA88=
github.com/networkservicemesh/sdk-kernel v0.0.0-20221205081316-4df325defbcc h1:7YcWR8xZonDsUY6dZ2EzevtetZ9+YMnmp/PMe08ucmk=
Expand Down
11 changes: 9 additions & 2 deletions pkg/networkservice/chains/forwarder/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ import (
"context"
"net"
"net/url"
"sync"
"time"

"git.fd.io/govpp.git/api"
"github.com/google/uuid"

"github.com/networkservicemesh/api/pkg/api/networkservice"
ipsecapi "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/ipsec"

"github.com/networkservicemesh/sdk/pkg/networkservice/chains/client"
"github.com/networkservicemesh/sdk/pkg/networkservice/chains/endpoint"
"github.com/networkservicemesh/sdk/pkg/networkservice/common/authorize"
Expand All @@ -54,6 +57,7 @@ import (
"github.com/networkservicemesh/sdk-kernel/pkg/kernel/networkservice/ethernetcontext"

"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/connectioncontext/mtu"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/ipsec"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/kernel"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/memif"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/vlan"
Expand Down Expand Up @@ -104,6 +108,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn
registryclient.WithDialOptions(opts.dialOpts...))

rv := &xconnectNSServer{}
pinholeMutex := new(sync.Mutex)
additionalFunctionality := []networkservice.NetworkServiceServer{
recvfd.NewServer(),
sendfd.NewServer(),
Expand All @@ -124,8 +129,9 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn
kernel.MECHANISM: kernel.NewServer(vppConn),
vxlan.MECHANISM: vxlan.NewServer(vppConn, tunnelIP, opts.vxlanOpts...),
wireguard.MECHANISM: wireguard.NewServer(vppConn, tunnelIP),
ipsecapi.MECHANISM: ipsec.NewServer(vppConn, tunnelIP),
}),
pinhole.NewServer(vppConn),
pinhole.NewServer(vppConn, pinhole.WithSharedMutex(pinholeMutex)),
connect.NewServer(
client.NewClient(ctx,
client.WithoutRefresh(),
Expand All @@ -148,9 +154,10 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, vppConn
kernel.NewClient(vppConn),
vxlan.NewClient(vppConn, tunnelIP, opts.vxlanOpts...),
wireguard.NewClient(vppConn, tunnelIP),
ipsec.NewClient(vppConn, tunnelIP),
vlan.NewClient(vppConn, opts.domain2Device),
filtermechanisms.NewClient(),
pinhole.NewClient(vppConn),
pinhole.NewClient(vppConn, pinhole.WithSharedMutex(pinholeMutex)),
recvfd.NewClient(),
nsmonitor.NewClient(ctx),
sendfd.NewClient(),
Expand Down
117 changes: 117 additions & 0 deletions pkg/networkservice/mechanisms/ipsec/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) 2022 Cisco and/or its affiliates.
//
// 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 ipsec

import (
"context"
"net"

"git.fd.io/govpp.git/api"
"github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors"
"google.golang.org/grpc"

"github.com/networkservicemesh/api/pkg/api/networkservice"
"github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/cls"
ipsecMech "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/ipsec"
"github.com/networkservicemesh/api/pkg/api/networkservice/payload"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/chain"
"github.com/networkservicemesh/sdk/pkg/networkservice/core/next"
"github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata"
"github.com/networkservicemesh/sdk/pkg/tools/postpone"

"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/mechanisms/ipsec/mtu"
"github.com/networkservicemesh/sdk-vpp/pkg/networkservice/pinhole"
)

type ipsecClient struct {
vppConn api.Connection
tunnelIP net.IP
}

// NewClient - returns a new client for the IPSec remote mechanism
func NewClient(vppConn api.Connection, tunnelIP net.IP) networkservice.NetworkServiceClient {
return chain.NewNetworkServiceClient(
&ipsecClient{
vppConn: vppConn,
tunnelIP: tunnelIP,
},
mtu.NewClient(vppConn, tunnelIP),
)
}

func (i *ipsecClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) {
if request.GetConnection().GetPayload() != payload.IP {
return next.Client(ctx).Request(ctx, request, opts...)
}

rsaKey, err := generateRSAKey()
if err != nil {
return nil, err
}
publicKey, err := createCertBase64(rsaKey, metadata.IsClient(i))
if err != nil {
return nil, err
}
// If we already have a key we can reuse it
// else create a new one and store it after successful interface creation
if mechanism := ipsecMech.ToMechanism(request.GetConnection().GetMechanism()); mechanism != nil {
// If there is a key in mechanism then we can use it
publicKey = mechanism.SrcPublicKey()
}
mechanism := &networkservice.Mechanism{
Cls: cls.REMOTE,
Type: ipsecMech.MECHANISM,
Parameters: make(map[string]string),
}
ipsecMech.ToMechanism(mechanism).
SetSrcPublicKey(publicKey).
SetSrcIP(i.tunnelIP).
SetSrcPort(ikev2DefaultPort)

request.MechanismPreferences = append(request.MechanismPreferences, mechanism)

// Store extra IPPort entry to allow IKE protocol - https://www.rfc-editor.org/rfc/rfc5996
pinhole.StoreExtra(ctx, metadata.IsClient(i), pinhole.NewIPPort(i.tunnelIP.String(), 500))

postponeCtxFunc := postpone.ContextWithValues(ctx)

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

if err = create(ctx, conn, i.vppConn, rsaKey, metadata.IsClient(i)); err != nil {
closeCtx, cancelClose := postponeCtxFunc()
defer cancelClose()

if _, closeErr := i.Close(closeCtx, conn, opts...); closeErr != nil {
err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error())
}

return nil, err
}

return conn, nil
}

func (i *ipsecClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) {
if mechanism := ipsecMech.ToMechanism(conn.GetMechanism()); mechanism != nil {
delInterface(ctx, conn, i.vppConn, metadata.IsClient(i))
}
return next.Client(ctx).Close(ctx, conn, opts...)
}
Loading

0 comments on commit ae72c6f

Please sign in to comment.