Documentation
¶
Index ¶
- func DeployClient(client *SSHClient, machineID, username, config string, logWriter io.Writer) error
- func ExecuteCommands(client *SSHClient, cmds []string, w io.Writer) error
- func ExecuteWithOutput(client *SSHClient, cmd string, w io.Writer) error
- func GenerateRSAKeypair() (string, string, error)
- func ValidateKeyPair(privateKeyPEM, publicAuthorizedKey string) error
- func ValidatePublicKey(publicAuthorizedKey string) error
- type SSHClient
- func (c *SSHClient) Close() error
- func (c *SSHClient) Execute(cmd string) (string, error)
- func (c *SSHClient) ExecuteWithOutput(cmd string, w io.Writer) error
- func (c *SSHClient) ReadFile(remotePath string) ([]byte, error)
- func (c *SSHClient) UploadFile(content []byte, remotePath string) error
- func (c *SSHClient) UploadFileSudo(content []byte, remotePath, owner string) error
- func (c *SSHClient) UploadFileSudoInPlace(content []byte, remotePath, owner string) error
- func (c *SSHClient) UploadReader(r io.Reader, remotePath string) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DeployClient ¶
func GenerateRSAKeypair ¶
GenerateRSAKeypair returns (privateKeyPEM, publicKeyAuthorizedKeys, error)
func ValidateKeyPair ¶
ValidateKeyPair checks that privateKeyPEM (PEM or OpenSSH format) and publicAuthorizedKey (authorized_keys line) form a matching pair.
func ValidatePublicKey ¶
ValidatePublicKey checks that publicAuthorizedKey is a well-formed authorized_keys line. Used when a key is registered public-only (no private half stored on the server).
Types ¶
type SSHClient ¶
type SSHClient struct {
// contains filtered or unexported fields
}
func NewClient ¶
NewClient dials an SSH endpoint with the supplied private key. Host-key verification is intentionally disabled because every caller dials a rathole-tunnel localhost port (or a bind_ip on the VPS itself) — there is no public network leg to MITM. An attacker positioned to hijack localhost/VPS-bound traffic already has the root-equivalent access that host-key pinning would normally protect against, so verification adds no real defense in our deployment shape (single-tenant VPS).
On a multi-tenant or shared host this would no longer hold; tracked against #9 in the pre-stable audit.
func (*SSHClient) ExecuteWithOutput ¶
func (*SSHClient) UploadFile ¶
func (*SSHClient) UploadFileSudo ¶
UploadFileSudo uploads content to remotePath. It first attempts a direct SFTP write (succeeds when the SSH user owns the file/directory). If that is denied, it uploads to a temp path the user can always write and uses "sudo mv" to install it. Pass owner="" to skip the chown step after the move.
IMPORTANT: this REPLACES the destination's inode (rename via mv). For files watched by an inotify-based hot reloader (rathole client.toml in particular), use UploadFileSudoInPlace instead — otherwise the watcher loses its subscription on first push and never sees subsequent changes without a process restart, which drops every connected tunnel.
func (*SSHClient) UploadFileSudoInPlace ¶
UploadFileSudoInPlace uploads content and writes it to remotePath while preserving the file's inode. Used for rathole client.toml: rathole 0.5's notify watcher subscribes to the inode, and rename(2)-based replacement silently breaks the subscription so subsequent config pushes never get hot-reloaded.
The strategy is the same two-step (SFTP to tmp, then privilege-escalate to install) as UploadFileSudo, but the second step uses `cat tmp > target` via `sudo tee` instead of `mv`. tee opens with O_TRUNC|O_WRONLY|O_CREATE, which keeps the inode and fires IN_MODIFY for the watcher.
If the SSH user already owns the destination, falls through to the direct SFTP path: sftpClient.Create truncates by default and preserves the inode.