mirror of
https://github.com/containers/gvisor-tap-vsock.git
synced 2025-12-24 13:29:22 +08:00
Add support for multiple unix socket forwards over ssh
This commit is contained in:
@@ -32,10 +32,10 @@ var (
|
||||
endpoints arrayFlags
|
||||
vpnkitSocket string
|
||||
qemuSocket string
|
||||
forwardSocket string
|
||||
forwardDest string
|
||||
forwardUser string
|
||||
forwardIdentify string
|
||||
forwardSocket arrayFlags
|
||||
forwardDest arrayFlags
|
||||
forwardUser arrayFlags
|
||||
forwardIdentify arrayFlags
|
||||
sshPort int
|
||||
pidFile string
|
||||
exitCode int
|
||||
@@ -53,10 +53,10 @@ func main() {
|
||||
flag.IntVar(&sshPort, "ssh-port", 2222, "Port to access the guest virtual machine. Must be between 1024 and 65535")
|
||||
flag.StringVar(&vpnkitSocket, "listen-vpnkit", "", "VPNKit socket to be used by Hyperkit")
|
||||
flag.StringVar(&qemuSocket, "listen-qemu", "", "Socket to be used by Qemu")
|
||||
flag.StringVar(&forwardSocket, "forward-sock", "", "Forwards a unix socket to the guest virtual machine over SSH")
|
||||
flag.StringVar(&forwardDest, "forward-dest", "", "Forwards a unix socket to the guest virtual machine over SSH")
|
||||
flag.StringVar(&forwardUser, "forward-user", "", "SSH user to use for unix socket forward")
|
||||
flag.StringVar(&forwardIdentify, "forward-identity", "", "Path to SSH identity key for forwarding")
|
||||
flag.Var(&forwardSocket, "forward-sock", "Forwards a unix socket to the guest virtual machine over SSH")
|
||||
flag.Var(&forwardDest, "forward-dest", "Forwards a unix socket to the guest virtual machine over SSH")
|
||||
flag.Var(&forwardUser, "forward-user", "SSH user to use for unix socket forward")
|
||||
flag.Var(&forwardIdentify, "forward-identity", "Path to SSH identity key for forwarding")
|
||||
flag.StringVar(&pidFile, "pid-file", "", "Generate a file with the PID in it")
|
||||
flag.Parse()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@@ -95,26 +95,16 @@ func main() {
|
||||
protocol = types.QemuProtocol
|
||||
}
|
||||
|
||||
forwardCount := 0
|
||||
if forwardDest != "" {
|
||||
forwardCount++
|
||||
}
|
||||
if forwardIdentify != "" {
|
||||
_, err := os.Stat(forwardIdentify)
|
||||
if err != nil {
|
||||
exitWithError(errors.Wrapf(err, "Identity file %s can't be loaded", forwardIdentify))
|
||||
}
|
||||
forwardCount++
|
||||
}
|
||||
if forwardUser != "" {
|
||||
forwardCount++
|
||||
}
|
||||
if forwardSocket != "" {
|
||||
forwardCount++
|
||||
if c := len(forwardSocket); c != len(forwardDest) || c != len(forwardUser) || c != len(forwardIdentify) {
|
||||
exitWithError(errors.New("-forward-sock, --forward-dest, --forward-user, and --forward-identity must all be specified together, " +
|
||||
"the same number of times, or not at all"))
|
||||
}
|
||||
|
||||
if forwardCount > 0 && forwardCount < 4 {
|
||||
exitWithError(errors.New("-forward-sock, --forward-dest, --forward-user, and --forward-identity must all be specified together, or none specified"))
|
||||
for i := 0; i < len(forwardSocket); i++ {
|
||||
_, err := os.Stat(forwardIdentify[i])
|
||||
if err != nil {
|
||||
exitWithError(errors.Wrapf(err, "Identity file %s can't be loaded", forwardIdentify[i]))
|
||||
}
|
||||
}
|
||||
|
||||
// Create a PID file if requested
|
||||
@@ -319,16 +309,17 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
|
||||
})
|
||||
}
|
||||
|
||||
if forwardSocket != "" {
|
||||
for i := 0; i < len(forwardSocket); i++ {
|
||||
dest := url.URL{
|
||||
Scheme: "ssh",
|
||||
User: url.User(forwardUser),
|
||||
User: url.User(forwardUser[i]),
|
||||
Host: sshHostPort,
|
||||
Path: forwardDest,
|
||||
Path: forwardDest[i],
|
||||
}
|
||||
j := i
|
||||
g.Go(func() error {
|
||||
defer os.Remove(forwardSocket)
|
||||
forward, err := CreateSSHForward(ctx, forwardSocket, dest, forwardIdentify, vn)
|
||||
defer os.Remove(forwardSocket[j])
|
||||
forward, err := CreateSSHForward(ctx, forwardSocket[j], dest, forwardIdentify[j], vn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -100,8 +100,6 @@ func setupProxy(ctx context.Context, socketURI *url.URL, dest *url.URL, identity
|
||||
return &SSHForward{}, err
|
||||
}
|
||||
|
||||
logrus.Infof("Socket forward listening on: %s\n", socketURI)
|
||||
|
||||
connectFunc := func(bastion *sshclient.Bastion) (net.Conn, error) {
|
||||
timeout := 5 * time.Second
|
||||
if bastion != nil {
|
||||
@@ -126,7 +124,7 @@ func setupProxy(ctx context.Context, socketURI *url.URL, dest *url.URL, identity
|
||||
return &SSHForward{}, err
|
||||
}
|
||||
|
||||
logrus.Infof("SSH Bastion connected: %s\n", dest)
|
||||
logrus.Infof("Socket forward established: %s to %s\n", socketURI.Path, dest.Path)
|
||||
|
||||
return &SSHForward{listener, &bastion, socketURI}, nil
|
||||
}
|
||||
|
||||
@@ -51,6 +51,13 @@ ExecStart=/usr/bin/sleep infinity
|
||||
"sudo",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "root",
|
||||
PasswordHash: &password,
|
||||
SSHAuthorizedKeys: []SSHAuthorizedKey{
|
||||
SSHAuthorizedKey(publicKey),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ address=/foobar/1.2.3.4
|
||||
}).Should(Succeed())
|
||||
})
|
||||
|
||||
It("should reach podman API using unix socket forwarding over ssh", func() {
|
||||
It("should reach rootless podman API using unix socket forwarding over ssh", func() {
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
@@ -198,4 +198,27 @@ address=/foobar/1.2.3.4
|
||||
g.Expect(string(reply)).To(Equal("OK"))
|
||||
}).Should(Succeed())
|
||||
})
|
||||
|
||||
It("should reach rootful podman API using unix socket forwarding over ssh", func() {
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return net.Dial("unix", forwardRootSock)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Eventually(func(g Gomega) {
|
||||
resp, err := httpClient.Get("http://host/_ping")
|
||||
g.Expect(err).ShouldNot(HaveOccurred())
|
||||
g.Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
g.Expect(resp.ContentLength).To(Equal(int64(2)))
|
||||
|
||||
reply := make([]byte, resp.ContentLength)
|
||||
_, err = io.ReadAtLeast(resp.Body, reply, len(reply))
|
||||
|
||||
g.Expect(err).ShouldNot(HaveOccurred())
|
||||
g.Expect(string(reply)).To(Equal("OK"))
|
||||
}).Should(Succeed())
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,26 +26,28 @@ func TestSuite(t *testing.T) {
|
||||
}
|
||||
|
||||
const (
|
||||
sock = "/tmp/gvproxy-api.sock"
|
||||
qemuPort = 5555
|
||||
sshPort = 2222
|
||||
ignitionUser = "test"
|
||||
qconLog = "qcon.log"
|
||||
podmanSock = "/run/user/1001/podman/podman.sock"
|
||||
sock = "/tmp/gvproxy-api.sock"
|
||||
qemuPort = 5555
|
||||
sshPort = 2222
|
||||
ignitionUser = "test"
|
||||
qconLog = "qcon.log"
|
||||
podmanSock = "/run/user/1001/podman/podman.sock"
|
||||
podmanRootSock = "/run/podman/podman.sock"
|
||||
|
||||
// #nosec "test" (for manual usage)
|
||||
ignitionPasswordHash = "$y$j9T$TqJWt3/mKJbH0sYi6B/LD1$QjVRuUgntjTHjAdAkqhkr4F73m.Be4jBXdAaKw98sPC"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpDir string
|
||||
binDir string
|
||||
host *exec.Cmd
|
||||
client *exec.Cmd
|
||||
privateKeyFile string
|
||||
publicKeyFile string
|
||||
ignFile string
|
||||
forwardSock string
|
||||
tmpDir string
|
||||
binDir string
|
||||
host *exec.Cmd
|
||||
client *exec.Cmd
|
||||
privateKeyFile string
|
||||
publicKeyFile string
|
||||
ignFile string
|
||||
forwardSock string
|
||||
forwardRootSock string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -55,6 +57,8 @@ func init() {
|
||||
publicKeyFile = privateKeyFile + ".pub"
|
||||
ignFile = filepath.Join(tmpDir, "test.ign")
|
||||
forwardSock = filepath.Join(tmpDir, "podman-remote.sock")
|
||||
forwardRootSock = filepath.Join(tmpDir, "podman-root-remote.sock")
|
||||
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
@@ -78,7 +82,10 @@ outer:
|
||||
// #nosec
|
||||
host = exec.Command(filepath.Join(binDir, "gvproxy"), fmt.Sprintf("--listen=unix://%s", sock), fmt.Sprintf("--listen-qemu=tcp://127.0.0.1:%d", qemuPort),
|
||||
fmt.Sprintf("--forward-sock=%s", forwardSock), fmt.Sprintf("--forward-dest=%s", podmanSock), fmt.Sprintf("--forward-user=%s", ignitionUser),
|
||||
fmt.Sprintf("--forward-identity=%s", privateKeyFile),
|
||||
fmt.Sprintf("--forward-sock=%s", forwardRootSock), fmt.Sprintf("--forward-dest=%s", podmanRootSock), fmt.Sprintf("--forward-user=%s", "root"),
|
||||
fmt.Sprintf("--forward-identity=%s", privateKeyFile))
|
||||
|
||||
host.Stderr = os.Stderr
|
||||
host.Stdout = os.Stdout
|
||||
Expect(host.Start()).Should(Succeed())
|
||||
|
||||
Reference in New Issue
Block a user