soratun

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2021 License: MIT Imports: 28 Imported by: 0

README

soratun check Go Report Card GoDoc

An easy-to-use, userspace SORACOM Arc client powered by wireguard-go. For deploying and scaling Linux servers/Raspberry Pi devices working with SORACOM platform and SORACOM Arc.

  • Quick deployment (copy one or two binary files and done)
  • Integration with SORACOM platform

Tested Platforms

  • Linux amd64
    • Ubuntu 20.04.2 LTS
  • Linux arm (Raspberry Pi 32-bit)
    • Raspberry Pi OS 2021-05-07
    • Ubuntu 20.04.2 LTS
  • macOS Big Sur 11.3 (20E232) -- For development and testing purpose only

Usage

soratun -- SORACOM Arc Client

Usage:
  soratun [command]

Available Commands:
  bootstrap   Create virtual SIM and configure soratun
  config      Create initial soratun configuration file without bootstrapping
  help        Help about any command
  status      Display SORACOM Arc interface status
  up          Setup SORACOM Arc interface
  version     Show version
  wg-config   Dump soratun configuration file as WireGuard format

Flags:
      --config string   Specify path to SORACOM Arc client configuration file (default "arc.json")
  -h, --help            help for soratun

Use "soratun [command] --help" for more information about a command.

See the schema (English / Japanese) for configuration file arc.json detail.

Getting Started
  1. SORACOM platform setup

    1. Create a new SAM user with following permission, and generate a pair of Auth Key and Auth Key Secret for SORACOM API, referring following official documents:

      {
        "statements": [
          {
            "api": ["Sim:createSim", "Sim:createArcSession"],
            "effect": "allow"
          }
        ]
      }
      
  2. SORACOM Arc bootstrap -- create a new virtual SIM and soratun configuration file

    1. Download the latest binary from the Releases section.

    2. Bootstrap with soratun bootstrap authkey command:

      $ ./soratun bootstrap authkey
      
    3. soratun will guide your setup through interactive wizard, with asking following questions:

      • SORACOM API auth key ID (starts with "keyId-")
      • SORACOM API auth key (starts with "secret-")
      • Coverage to create a new virtual SIM Global coverage (g.api.soracom.io) / Japan coverage (api.soracom.io)
    4. You will get following output from soratun:

      Created new virtual subscriber: 99999xxxxxxxxxx
      Created/updated configuration file: /path/to/arc.json
      
  3. Start soratun to connect to SORACOM platform:

    $ sudo ./soratun up
    $ ping pong.soracom.io
    

Tips: you can skip interactive wizard by supplying required parameters via flags as follows.

$ soratun bootstrap authkey --auth-key-id keyId-xxx --auth-key secret-xxx --coverage-type jp

For other bootstrapping method detail, please consult SORACOM documentation at:

Running as a daemon with systemd

Use conf/soratun.service.sample as a starter, copy file you edited to /etc/systemd/system/soratun.service directory, then

$ sudo systemctl enable soratun
$ sudo systemctl start soratun
$ sudo systemctl status soratun
$ journalctl -u soratun -f
$ sudo systemctl stop soratun

soratun supports systemd watchdog. It'll update the timer every 110 seconds, based on Protocol & Cryptography - WireGuard:

After receiving a packet, if the receiver was the original initiator of the handshake and if the current session key is REKEY_AFTER_TIME - KEEPALIVE_TIMEOUT - REKEY_TIMEOUT ms old, we initiate a new handshake.

With the sample unit configuration, soratun will be restarted after max. 120 + 110 seconds after Arc session deletion. This timer would be reconsidered in the future.

Running without sudo

You can run soratun without sudo as follows. See capabilities(7) for CAP_NET_ADMIN detail.

$ sudo groupadd wg # create a new group for WireGuard users
$ sudo mkdir -p /var/run/wireguard # create a directory where wireguard-go control socket file persists
$ sudo chgrp wg /var/run/wireguard # change group of the directory
$ sudo setcap cap_net_admin+epi soratun # add CAP_NET_ADMIN capability to perform various network related operations
$ sudo usermod -a -G wg ubuntu # update group for WireGuard user
$ # log out to enable group change
$ soratun up soratun0 --log-level verbose

Note: Some OSes won't persist /var/run/wireguard during OS recycle. We have to find more good way to do this.

Shell autocompletion

soratun will generate the autocompletion script for bash and zsh. See soratun completion --help for detail. The completion subcommand is hidden from soratun --help.

TODOs

More test coverage.

License

See LICENSE for detail.

Acknowledgments

"WireGuard" and the "WireGuard" logo are registered trademarks of Jason A. Donenfeld.

Following source codes have been derived from wireguard-go which is copyrighted by WireGuard LLC under the terms of the license.

Note

This project is not affiliated with the WireGuard project.

Contributing

Please see CONTRIBUTING for detail.

FAQ

  • Why I should use this although recent Linux kernel has first class WireGuard support?
    1. In order to make SORACOM Arc deployment and configuration simple. This client is tightly integrated with SORACOM platform and will do essential steps such as authentication, configuration, etc. on behalf of you.
    2. Of course, you can use Linux kernel-native WireGuard with manual setup.
    3. In the future, SORACOM Arc might introduce new technology other than WireGuard, but (hopefully) this program will make the changes invisible under the hood.
  • Why the operating system XXX is not supported?
    1. Platforms supported by wireguard-go should work. But please note that this client will set required network configurations up via Netlink. Other platform which don't have similar capability will need manual adjustments.
    2. SORACOM API is platform agnostic so implementation related to that part should work as well, but not tested.

Documentation

Overview

Package soratun implements userspace SORACOM Arc client.

Index

Constants

View Source
const (
	// LogLevelVerbose is an alias for WireGuard device logger equivalent.
	LogLevelVerbose = device.LogLevelVerbose
	// LogLevelError is an alias for WireGuard device logger equivalent.
	LogLevelError = device.LogLevelError
	// LogLevelSilent is an alias for WireGuard device logger equivalent.
	LogLevelSilent = device.LogLevelSilent
	// DefaultPersistentKeepaliveInterval defines WireGuard persistent keepalive interval to SORACOM Arc.
	DefaultPersistentKeepaliveInterval = 60
	// DefaultMTU is MTU for the configured interface.
	DefaultMTU = device.DefaultMTU
)

Variables

This section is empty.

Functions

func ConfigureInterface

func ConfigureInterface(iname string, config *Config) error

ConfigureInterface create a new network interface with given SORACOM Arc configuration. Then setup routing table for allowedIPs.

func DefaultInterfaceName

func DefaultInterfaceName() string

DefaultInterfaceName returns a default interface name

func Up

func Up(ctx context.Context, config *Config)

Up ups new SORACOM Arc tunnel with given ArcSession.

Types

type ArcSession

type ArcSession struct {
	// ArcServerPeerPublicKey is WireGuard public key of the SORACOM Arc server.
	ArcServerPeerPublicKey Key `json:"arcServerPeerPublicKey"`
	// ArcServerEndpoint is a UDP endpoint of the SORACOM Arc server.
	ArcServerEndpoint *UDPAddr `json:"arcServerEndpoint"`
	// ArcAllowedIPs holds IP addresses allowed for routing from the SORACOM Arc server.
	ArcAllowedIPs []*IPNet `json:"arcAllowedIPs"`
	// ArcClientPeerPrivateKey holds private key from SORACOM Arc server.
	ArcClientPeerPrivateKey Key `json:"arcClientPeerPrivateKey,omitempty"`
	// ArcClientPeerIpAddress is an IP address for this client.
	ArcClientPeerIpAddress net.IP `json:"arcClientPeerIpAddress,omitempty"`
}

ArcSession holds SORACOM Arc configurations received from the server.

func (*ArcSession) MarshalJSON

func (a *ArcSession) MarshalJSON() ([]byte, error)

MarshalJSON converts struct to JSON, omitting ArcClientPeerPrivateKey field which is redundant for configuration file.

type AuthKeyBootstrapper

type AuthKeyBootstrapper struct {
	Profile *Profile
}

AuthKeyBootstrapper defines bootstrap method with SORACOM API authentication. Needs Profile information.

func (*AuthKeyBootstrapper) Execute

func (b *AuthKeyBootstrapper) Execute(config *Config) (*Config, error)

Execute calls SORACOM API to create a new standalone virtual subscriber.

type Bootstrapper

type Bootstrapper interface {
	Execute(config *Config) (*Config, error)
}

Bootstrapper defines how to bootstrap virtual SIM with SORACOM.

type CellularBootstrapper

type CellularBootstrapper struct {
	Endpoint string
}

CellularBootstrapper defines bootstrap method with SORACOM Krypton cellular authentication. Needs active cellular connection.

func (*CellularBootstrapper) Execute

func (b *CellularBootstrapper) Execute(config *Config) (*Config, error)

Execute calls SORACOM Krypton Provisioning API cellular endpoint to create a new virtual subscriber which is associated with current physical SIM.

type Config

type Config struct {
	// PrivateKey is WireGuard private key.
	PrivateKey Key `json:"privateKey"`
	// PublicKey is WireGuard public key.
	PublicKey Key `json:"publicKey"`
	// SimId is virtual SIM's SimId for the connection.
	SimId string `json:"simId"`
	// LogLevel specifies logging level, verbose, error, or silent.
	LogLevel int `json:"logLevel"`
	// If EnableMetrics is true, metrics will be logged when log-level is verbose or error.
	EnableMetrics bool `json:"enableMetrics"`
	// Interface is name for the tunnel interface.
	Interface string `json:"interface"`
	// AdditionalAllowedIPs holds a set of WireGuard allowed IPs in addition to the list which will get while creating Arc session.
	AdditionalAllowedIPs []*IPNet `json:"additionalAllowedIPs,omitempty"`
	// Mtu of the interface.
	Mtu int `json:"mtu,omitempty"`
	// WireGuard PersistentKeepalive parameter.
	PersistentKeepalive int `json:"persistentKeepalive,omitempty"`
	// PostUp is array of commands which will be executed after the interface is up successfully.
	PostUp [][]string `json:"postUp,omitempty"`
	// PostDown is array of commands which will be executed after the interface is removed successfully.
	PostDown [][]string `json:"postDown,omitempty"`
	// Profile is for SORACOM API access.
	Profile *Profile `json:"profile,omitempty"`
	// ArcSession holds connection information provided from SORACOM Arc server.
	ArcSession *ArcSession `json:"arcSessionStatus,omitempty"`
}

Config holds SORACOM Arc client configurations.

type DefaultSoracomClient

type DefaultSoracomClient struct {
	// contains filtered or unexported fields
}

DefaultSoracomClient is an implementation of the SoracomClient for the general use case.

func (*DefaultSoracomClient) CreateArcSession

func (c *DefaultSoracomClient) CreateArcSession(simId, publicKey string) (*ArcSession, error)

CreateArcSession creates new Arc session.

func (*DefaultSoracomClient) CreateVirtualSim

func (c *DefaultSoracomClient) CreateVirtualSim() (*VirtualSim, error)

CreateVirtualSim creates new virtual SIM.

func (*DefaultSoracomClient) SetVerbose

func (c *DefaultSoracomClient) SetVerbose(v bool)

SetVerbose sets if verbose output is enabled or not.

func (*DefaultSoracomClient) Verbose

func (c *DefaultSoracomClient) Verbose() bool

Verbose returns if verbose output is enabled or not.

type DefaultSoracomKryptonClient

type DefaultSoracomKryptonClient struct {
	// contains filtered or unexported fields
}

DefaultSoracomKryptonClient is an implementation of the SoracomKryptonClient for the general use case.

func (*DefaultSoracomKryptonClient) Bootstrap

func (c *DefaultSoracomKryptonClient) Bootstrap() (*ArcSession, error)

Bootstrap bootstraps Arc virtual SIM.

func (*DefaultSoracomKryptonClient) BootstrapWithKeyID

func (c *DefaultSoracomKryptonClient) BootstrapWithKeyID() (*ArcSession, error)

BootstrapWithKeyID bootstraps Arc virtual SIM with SIM authentication.

func (*DefaultSoracomKryptonClient) SetVerbose

func (c *DefaultSoracomKryptonClient) SetVerbose(v bool)

SetVerbose sets if verbose output is enabled or not.

func (*DefaultSoracomKryptonClient) Verbose

func (c *DefaultSoracomKryptonClient) Verbose() bool

Verbose returns if verbose output is enabled or not.

type IPNet

type IPNet net.IPNet

IPNet is an alias for net.IPNet.

func (*IPNet) MarshalText

func (n *IPNet) MarshalText() ([]byte, error)

MarshalText converts struct to a string.

func (*IPNet) UnmarshalText

func (n *IPNet) UnmarshalText(text []byte) error

UnmarshalText converts a byte array into IPNet. UnmarshalText returns error if invalid CIDR is provided.

type Key

type Key wgtypes.Key

Key is an alias for wgtypes.Key.

func NewKey

func NewKey(s string) (Key, error)

NewKey returns a Key from a base64-encoded string.

func (*Key) AsHexString

func (k *Key) AsHexString() string

AsHexString returns hexadecimal encoding of Key.

func (*Key) AsWgKey

func (k *Key) AsWgKey() *wgtypes.Key

AsWgKey converts Key back to wgtypes.Key.

func (*Key) MarshalText

func (k *Key) MarshalText() ([]byte, error)

MarshalText encodes Key to an array of bytes.

func (Key) String

func (k Key) String() string

String returns string representation of Key.

func (*Key) UnmarshalText

func (k *Key) UnmarshalText(text []byte) error

UnmarshalText decodes a byte array of private key to the Key. If text is invalid WireGuard key, UnmarshalText returns an error.

type KryptonClientConfig

type KryptonClientConfig struct {
	Endpoint string
}

A KryptonClientConfig holds SORACOM Krypton provisioning API client related information.

type Profile

type Profile struct {
	// AuthKey is SORACOM API auth key secret.
	AuthKey string `json:"authKey,omitempty"`
	// AuthKeyID is SORACOM API auth key ID.
	AuthKeyID string `json:"authKeyId,omitempty"`
	// Endpoint is SORACOM API endpoint.
	Endpoint string `json:"endpoint,omitempty"`
}

A Profile holds SORACOM API client related information.

type SimBootstrapper

type SimBootstrapper struct {
	KryptonCliPath string
	Arguments      []string
}

SimBootstrapper defines bootstrap method with SORACOM Krypton SIM authentication. Needs krypton-cli installed.

func (*SimBootstrapper) Execute

func (b *SimBootstrapper) Execute(config *Config) (*Config, error)

Execute calls SORACOM Krypton CLI to create a new virtual subscriber which is associated with current physical SIM.

type SimProfile

type SimProfile struct {
	// Iccid is ICCID of the subscriber.
	Iccid string `json:"iccid"`
	// ArcClientPeerPrivateKey is WireGuard private key of the subscriber.
	ArcClientPeerPrivateKey string `json:"arcClientPeerPrivateKey"`
	// ArcClientPeerPublicKey is WireGuard public key of the subscriber.
	ArcClientPeerPublicKey string `json:"arcClientPeerPublicKey"`
	// PrimaryImsi is Imsi of this virtual SIM.
	PrimaryImsi string `json:"primaryImsi"`
}

SimProfile is a SIM profile which holds one of profiles in the subscription container.

type SoracomClient

type SoracomClient interface {
	CreateVirtualSim() (*VirtualSim, error)
	CreateArcSession(simId, publicKey string) (*ArcSession, error)
	SetVerbose(v bool)
	Verbose() bool
}

A SoracomClient represents an API client for SORACOM API. See https://developers.soracom.io/en/docs/tools/api-reference/ or https://dev.soracom.io/jp/docs/api_guide/

func NewDefaultSoracomClient

func NewDefaultSoracomClient(p Profile) (SoracomClient, error)

NewDefaultSoracomClient returns new SoracomClient for caller.

type SoracomKryptonClient

type SoracomKryptonClient interface {
	Bootstrap() (*ArcSession, error)
	SetVerbose(v bool)
	Verbose() bool
}

A SoracomKryptonClient represents a maybe-over-complicated API client for SORACOM Krypton Provisioning API. See https://developers.soracom.io/en/api/krypton/ https://users.soracom.io/ja-jp/tools/krypton-api/

func NewDefaultSoracomKryptonClient

func NewDefaultSoracomKryptonClient(config *KryptonClientConfig) SoracomKryptonClient

NewDefaultSoracomKryptonClient returns new SoracomClient for caller.

type UDPAddr

type UDPAddr struct {
	IP          net.IP
	Port        int
	RawEndpoint []byte
}

UDPAddr represents the UDP address with keeping original endpoint.

func (*UDPAddr) MarshalText

func (a *UDPAddr) MarshalText() ([]byte, error)

MarshalText converts struct to a string.

func (*UDPAddr) UnmarshalText

func (a *UDPAddr) UnmarshalText(text []byte) error

UnmarshalText converts a byte array into UDPAddr. UnmarshalText returns error if the format is invalid (not "ip" or "ip:port"), IP address specified is invalid, or the port is not a 16-bit unsigned integer.

type VirtualSim

type VirtualSim struct {
	// OperatorId is operator ID of the subscriber.
	OperatorId string `json:"operatorId"`
	// Status is virtual SIM status, active or terminated as of 2021 first release.
	Status string `json:"status"`
	// SimId is SIM ID of the subscriber.
	SimId string `json:"simId"`
	// ArcSession holds Arc connection information.
	ArcSession ArcSession `json:"arcSessionStatus"`
	// Profiles holds series of SimProfile, (not SORACOM API Profile).
	Profiles map[string]SimProfile `json:"profiles"`
}

VirtualSim represents virtual subscriber.

Directories

Path Synopsis
cmd
mock
Package mock_soratun is a generated GoMock package.
Package mock_soratun is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL