Skip to content

Commit

Permalink
Adding option to connect SSH over proxy.
Browse files Browse the repository at this point in the history
  • Loading branch information
edimarlnx committed Mar 18, 2024
1 parent aa5c9a9 commit 55a1cfc
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 21 deletions.
72 changes: 51 additions & 21 deletions libvirt/uri/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package uri
import (
"fmt"
"github.com/trzsz/trzsz-ssh/tssh"
"golang.org/x/net/proxy"
"log"
"net"
"net/url"
"os"
"os/user"
"strings"
Expand Down Expand Up @@ -146,7 +148,7 @@ func (u *ConnectionURI) dialSSH() (net.Conn, error) {

sshClient, err := u.sshClient(cfg)
if err != nil {
return nil, err
log.Fatal(err)
}

address := q.Get("socket")
Expand All @@ -165,35 +167,63 @@ func (u *ConnectionURI) dialSSH() (net.Conn, error) {
func (u *ConnectionURI) sshClient(cfg ssh.ClientConfig) (*ssh.Client, error) {
q := u.Query()
sshControlPath := q.Get("SSHControlPath")
proxyURI := proxyByEnvVar()
port := u.Port()
if port == "" {
port = defaultSSHPort
}
if sshControlPath == "" {
if sshControlPath == "" && proxyURI == "" {
return ssh.Dial("tcp", fmt.Sprintf("%s:%s", u.Hostname(), port), &cfg)
}
sshControlPath = os.ExpandEnv(strings.Replace(sshControlPath, "~", "$HOME", 1))
_, err := os.Stat(sshControlPath)
if err != nil || os.IsNotExist(err) {
return nil, err
}
controlSocketConn, err := net.Dial("unix", sshControlPath)
if err != nil {
return nil, err
}
controlConn, chans, reqs, err := tssh.NewControlClientConn(controlSocketConn)
if err != nil {
return nil, err
}
sshControlClient := ssh.NewClient(controlConn, chans, reqs)
sshControlClientConn, err := sshControlClient.Dial("tcp", fmt.Sprintf("%s:%s", u.Hostname(), port))
if err != nil {
return nil, err
var proxyConn net.Conn
if sshControlPath != "" {
sshControlPath = os.ExpandEnv(strings.Replace(sshControlPath, "~", "$HOME", 1))
_, err := os.Stat(sshControlPath)
if err != nil || os.IsNotExist(err) {
return nil, err
}
controlSocketConn, err := net.Dial("unix", sshControlPath)
if err != nil {
return nil, err
}
controlConn, chans, reqs, err := tssh.NewControlClientConn(controlSocketConn)
if err != nil {
return nil, err
}
sshControlClient := ssh.NewClient(controlConn, chans, reqs)
sshControlClientConn, err := sshControlClient.Dial("tcp", fmt.Sprintf("%s:%s", u.Hostname(), port))
if err != nil {
return nil, err
}
proxyConn = sshControlClientConn
} else {
parsedProxyURI, err := url.Parse(proxyURI)
if err != nil || os.IsNotExist(err) {
return nil, err
}
dialer, err := proxy.SOCKS5(parsedProxyURI.Scheme, parsedProxyURI.Host, nil, proxy.Direct)
if err != nil {
return nil, err
}
socketConn, err := dialer.Dial("tcp", u.Host)
if err != nil {
return nil, err
}
proxyConn = socketConn
}
ncc, chans, reqs, err := ssh.NewClientConn(sshControlClientConn, fmt.Sprintf("%s:%s", u.Hostname(), port), &cfg)

ncc, chans, reqs, err := ssh.NewClientConn(proxyConn, fmt.Sprintf("%s:%s", u.Hostname(), port), &cfg)
if err != nil {
return nil, err
}
return ssh.NewClient(ncc, chans, reqs), nil
cli := ssh.NewClient(ncc, chans, reqs)
return cli, nil
}

func proxyByEnvVar() string {
proxyURL := os.Getenv("HTTP_PROXY")
if proxyURL != "" {
return proxyURL
}
return os.Getenv("ALL_PROXY")
}
2 changes: 2 additions & 0 deletions website/docs/index.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ The following keys can be used to configure the provider.
* `SSHControlPath` - The [SSH control path](https://man.openbsd.org/ssh_config#ControlPath) is used to reuse previous SSH connections, such as an SSH Gateway or SSH with MFA enabled.
* Ex.: `qemu+ssh://[email protected]/system?SSHControlPath=~/.ssh/ssh-gateway.socket&sshauth=agent`

_You can use the `HTTP_PROXY` or `ALL_PROXY` environment variables to create an SSH connection using a proxy. Ex.: `HTTP_PROXY=tcp://localhost:8022`_

## Environment variables

The libvirt connection URI can also be specified with the `LIBVIRT_DEFAULT_URI`
Expand Down

0 comments on commit 55a1cfc

Please sign in to comment.