mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-22 10:31:35 +00:00
vsudd: Make incoming socket forwarding more generic
Rather than hardcoding a single vsock<->docker.sock mapping allow arbitrary incoming connection forwarding between vsocks and unix domain sockets. The intention was to subsequently extend this further to support arbitrary forwarding of outgoing connections too and to use that to forward the syslog socket out to a vsock. This turned out not to be a good plan, partly since the syslog socket needs to be SOCK_DATAGRAM but vsocks only does SOCK_STREAM today (meaning we need some additional framing here) and partly because handling syslog forwarding in common code makes error logging in the common code somewhat trickier (logging syslog errors over syslog). So instead syslog will be handled as a special case in a following patch. However some vestiges of the original plan remain, e.g. the inForwards name and the net field in the forwards which could be unixgram but currently is only supporting unix(stream). In principal this patch could be dropped, but it adds some flexibility which might be useful in the future. Signed-off-by: Ian Campbell <ian.campbell@docker.com>
This commit is contained in:
parent
f70ff0aeac
commit
b61451047d
@ -9,12 +9,12 @@ depend()
|
||||
|
||||
start()
|
||||
{
|
||||
ebegin "Starting docker socket vsock passthrough"
|
||||
ebegin "Starting vsock proxy"
|
||||
|
||||
if [ -d /sys/bus/vmbus ]; then
|
||||
PORT=23a432c2-537a-4291-bcb5-d62504644739
|
||||
DOCKER_PORT=23a432c2-537a-4291-bcb5-d62504644739
|
||||
else
|
||||
PORT=2376
|
||||
DOCKER_PORT=2376
|
||||
fi
|
||||
|
||||
[ -n "${PIDFILE}" ] || PIDFILE=/var/run/vsudd.pid
|
||||
@ -25,7 +25,7 @@ start()
|
||||
--exec /sbin/vsudd \
|
||||
--make-pidfile --pidfile ${PIDFILE} \
|
||||
--stderr "${LOGFILE}" --stdout "${LOGFILE}" \
|
||||
-- -port "${PORT}" -sock /var/run/docker.sock
|
||||
-- -inport "${DOCKER_PORT}:unix:/var/run/docker.sock"
|
||||
|
||||
eend $? "Failed to start vsudd"
|
||||
}
|
||||
|
@ -2,12 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -15,11 +17,18 @@ import (
|
||||
"github.com/rneugeba/virtsock/go/vsock"
|
||||
)
|
||||
|
||||
type forward struct {
|
||||
vsock string
|
||||
net string // "unix" or "unixgram"
|
||||
usock string
|
||||
}
|
||||
|
||||
type forwards []forward
|
||||
|
||||
var (
|
||||
portstr string
|
||||
sock string
|
||||
detach bool
|
||||
useHVsock bool
|
||||
inForwards forwards
|
||||
detach bool
|
||||
useHVsock bool
|
||||
)
|
||||
|
||||
type vConn interface {
|
||||
@ -28,9 +37,25 @@ type vConn interface {
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
func (f *forwards) String() string {
|
||||
return "Forwards"
|
||||
}
|
||||
|
||||
func (f *forwards) Set(value string) error {
|
||||
s := strings.SplitN(value, ":", 3)
|
||||
if len(s) != 3 {
|
||||
return fmt.Errorf("Failed to parse: %s", value)
|
||||
}
|
||||
var newF forward
|
||||
newF.vsock = s[0]
|
||||
newF.net = s[1]
|
||||
newF.usock = s[2]
|
||||
*f = append(*f, newF)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&portstr, "port", "2376", "vsock port to forward")
|
||||
flag.StringVar(&sock, "sock", "/var/run/docker.sock", "path of the local Unix domain socket to forward to")
|
||||
flag.Var(&inForwards, "inport", "incoming port to forward")
|
||||
flag.BoolVar(&detach, "detach", false, "detach from terminal")
|
||||
}
|
||||
|
||||
@ -54,46 +79,69 @@ func main() {
|
||||
syscall.Dup2(int(fd), int(os.Stderr.Fd()))
|
||||
}
|
||||
|
||||
var l net.Listener
|
||||
if strings.Contains(portstr, "-") {
|
||||
svcid, err := hvsock.GuidFromString(portstr)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to parse GUID", portstr, err)
|
||||
}
|
||||
l, err = hvsock.Listen(hvsock.HypervAddr{VmId: hvsock.GUID_WILDCARD, ServiceId: svcid})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to bind to hvsock port: %s", err)
|
||||
}
|
||||
log.Printf("Listening on ServiceId %s", svcid)
|
||||
useHVsock = true
|
||||
} else {
|
||||
port, err := strconv.ParseUint(portstr, 10, 32)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't convert %s to a uint.", portstr, err)
|
||||
}
|
||||
l, err = vsock.Listen(uint(port))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to bind to vsock port %u: %s", port, err)
|
||||
}
|
||||
log.Printf("Listening on port %u", port)
|
||||
useHVsock = false
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
|
||||
connid := 0
|
||||
for {
|
||||
connid++
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Error accepting connection: %s", err)
|
||||
return // no more listening
|
||||
}
|
||||
log.Printf("Connection %d from: %s\n", connid, conn.RemoteAddr())
|
||||
|
||||
go handleOne(connid, conn.(vConn))
|
||||
for _, inF := range inForwards {
|
||||
var portstr = inF.vsock
|
||||
var network = inF.net
|
||||
var usock = inF.usock
|
||||
|
||||
var l net.Listener
|
||||
|
||||
if network != "unix" {
|
||||
log.Fatalf("cannot forward incoming port to %s:%s", network, usock)
|
||||
}
|
||||
|
||||
log.Printf("incoming port forward from %s to %s", portstr, usock)
|
||||
|
||||
if strings.Contains(portstr, "-") {
|
||||
svcid, err := hvsock.GuidFromString(portstr)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to parse GUID", portstr, err)
|
||||
}
|
||||
l, err = hvsock.Listen(hvsock.HypervAddr{VmId: hvsock.GUID_WILDCARD, ServiceId: svcid})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to bind to hvsock port: %s", err)
|
||||
}
|
||||
log.Printf("Listening on ServiceId %s", svcid)
|
||||
useHVsock = true
|
||||
} else {
|
||||
port, err := strconv.ParseUint(portstr, 10, 32)
|
||||
if err != nil {
|
||||
log.Fatalln("Can't convert %s to a uint.", portstr, err)
|
||||
}
|
||||
l, err = vsock.Listen(uint(port))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to bind to vsock port %d: %s", port, err)
|
||||
}
|
||||
log.Printf("Listening on port %s", portstr)
|
||||
useHVsock = false
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for {
|
||||
connid++
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Printf("Error accepting connection: %s", err)
|
||||
return // no more listening
|
||||
}
|
||||
log.Printf("Connection %d to: %s from: %s\n", connid, portstr, conn.RemoteAddr())
|
||||
|
||||
go handleOneIn(connid, conn.(vConn), usock)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func handleOne(connid int, conn vConn) {
|
||||
func handleOneIn(connid int, conn vConn, sock string) {
|
||||
defer func() {
|
||||
if err := conn.Close(); err != nil {
|
||||
// On windows we get an EINVAL when the other end already closed
|
||||
|
Loading…
Reference in New Issue
Block a user