mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-27 21:55:07 +03:00
Introduce VSOCK link type
This address family is used in communication between virtual machines and their hosts. Advantages include that no virtual ethernet adapter and their respective address configuration and routing need to be setup. Rather, with this new link type, only a single yggdrasil interface can exist inside of the virtual machine. It can also be used inside of containers. There, the advantage over existing link types like unix sockets include, that no mount point need to be shared with the host and container. This provides more isolation. More information: https://man7.org/linux/man-pages/man7/vsock.7.html https://gist.github.com/nrdmn/7971be650919b112343b1cb2757a3fe6
This commit is contained in:
parent
73705ff09d
commit
7ad7eb05d4
5 changed files with 88 additions and 0 deletions
|
@ -26,6 +26,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
- in case of vulnerabilities.
|
||||
-->
|
||||
|
||||
## [0.5.xx] - 2025-xx-xx
|
||||
|
||||
### Added
|
||||
|
||||
* VSOCK support for peerings, by using the new `vsock://` scheme in `Listen` and `Peers`.
|
||||
* Use e.g. `vsock://local:1234`.
|
||||
|
||||
## [0.5.12] - 2024-12-18
|
||||
|
||||
* Go 1.22 is now required to build Yggdrasil
|
||||
|
|
2
go.mod
2
go.mod
|
@ -11,6 +11,7 @@ require (
|
|||
github.com/hashicorp/go-syslog v1.0.0
|
||||
github.com/hjson/hjson-go/v4 v4.4.0
|
||||
github.com/kardianos/minwinsvc v1.0.2
|
||||
github.com/mdlayher/vsock v1.2.1
|
||||
github.com/quic-go/quic-go v0.48.2
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
github.com/wlynxg/anet v0.0.5
|
||||
|
@ -29,6 +30,7 @@ require (
|
|||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -50,6 +50,10 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
|
||||
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
|
|
|
@ -40,6 +40,7 @@ type links struct {
|
|||
quic *linkQUIC // QUIC interface support
|
||||
ws *linkWS // WS interface support
|
||||
wss *linkWSS // WSS interface support
|
||||
vsock *linkVSOCK // VSOCK interface support
|
||||
// _links can only be modified safely from within the links actor
|
||||
_links map[linkInfo]*link // *link is nil if connection in progress
|
||||
_listeners map[*Listener]context.CancelFunc
|
||||
|
@ -96,6 +97,7 @@ func (l *links) init(c *Core) error {
|
|||
l.quic = l.newLinkQUIC()
|
||||
l.ws = l.newLinkWS()
|
||||
l.wss = l.newLinkWSS()
|
||||
l.vsock = l.newLinkVSOCK()
|
||||
l._links = make(map[linkInfo]*link)
|
||||
l._listeners = make(map[*Listener]context.CancelFunc)
|
||||
|
||||
|
@ -444,6 +446,8 @@ func (l *links) listen(u *url.URL, sintf string, local bool) (*Listener, error)
|
|||
protocol = l.ws
|
||||
case "wss":
|
||||
protocol = l.wss
|
||||
case "vsock":
|
||||
protocol = l.vsock
|
||||
default:
|
||||
ctxcancel()
|
||||
return nil, ErrLinkUnrecognisedSchema
|
||||
|
@ -595,6 +599,8 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
|
|||
dialer = l.ws
|
||||
case "wss":
|
||||
dialer = l.wss
|
||||
case "vsock":
|
||||
dialer = l.vsock
|
||||
default:
|
||||
return nil, ErrLinkUnrecognisedSchema
|
||||
}
|
||||
|
|
69
src/core/link_vsock.go
Normal file
69
src/core/link_vsock.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"github.com/mdlayher/vsock"
|
||||
)
|
||||
|
||||
type linkVSOCK struct {
|
||||
phony.Inbox
|
||||
*links
|
||||
}
|
||||
|
||||
func (l *links) newLinkVSOCK() *linkVSOCK {
|
||||
lt := &linkVSOCK{
|
||||
links: l,
|
||||
}
|
||||
return lt
|
||||
}
|
||||
|
||||
func (l *linkVSOCK) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
|
||||
localPort, err := strconv.ParseUint(url.Port(), 10, 32)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no VSOCK port specified: %w", err)
|
||||
}
|
||||
contextID, err := urlParseContextID(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unknown VSOCK host and cannot parse as numerical contextID: %w", err)
|
||||
}
|
||||
return vsock.Dial(contextID, uint32(localPort), nil)
|
||||
}
|
||||
|
||||
func (l *linkVSOCK) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
|
||||
localPort, err := strconv.ParseUint(url.Port(), 10, 32)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no VSOCK port specified: %w", err)
|
||||
}
|
||||
contextID, err := urlParseContextID(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unknown VSOCK host and cannot parse as numerical contextID: %w", err)
|
||||
}
|
||||
return vsock.ListenContextID(contextID, uint32(localPort), nil)
|
||||
}
|
||||
|
||||
func urlParseContextID(u *url.URL) (uint32, error) {
|
||||
var contextID uint32
|
||||
|
||||
switch strings.ToLower(u.Hostname()) {
|
||||
case "hypervisor":
|
||||
contextID = vsock.Hypervisor
|
||||
case "local":
|
||||
contextID = vsock.Local
|
||||
case "host":
|
||||
contextID = vsock.Host
|
||||
default:
|
||||
parsedHost, err := strconv.ParseUint(u.Hostname(), 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
contextID = uint32(parsedHost)
|
||||
}
|
||||
return contextID, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue