Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ jobs:
uses: actions/setup-go@v7
with:
go-version-file: go.mod
cache-dependency-path: |
go.sum
go.tools.sum
check-latest: true
- name: Setup golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.12
args: --verbose
- name: Run golangci-lint
run: make lint

testing:
runs-on: ubuntu-latest
container: golang:1.25-alpine
strategy:
matrix:
go: ["1.26", "1.27"]
name: Go ${{ matrix.go }}
container: golang:${{ matrix.go }}-alpine
steps:
- name: Checkout
uses: actions/checkout@v7
Expand Down
15 changes: 10 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
GOFMT ?= gofumpt -l -s
GO ?= go
TOOLS_MOD := -modfile=go.tools.mod
PACKAGES ?= $(shell $(GO) list ./...)
SOURCES ?= $(shell find . -name "*.go" -type f)

all: lint

fmt:
@hash gofumpt > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) install mvdan.cc/gofumpt; \
fi
$(GOFMT) -w $(SOURCES)
$(GO) tool $(TOOLS_MOD) golangci-lint fmt

vet:
$(GO) vet $(PACKAGES)
Expand Down Expand Up @@ -44,3 +41,11 @@ ssh-server:
sed -i 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config
sed -i 's/AllowTcpForwarding no/AllowTcpForwarding yes/g' /etc/ssh/sshd_config
./tests/entrypoint.sh /usr/sbin/sshd -D &

.PHONY: lint
lint: ## Run golangci-lint
$(GO) tool $(TOOLS_MOD) golangci-lint run

.PHONY: install-tools fmt lint
install-tools: ## Download pinned Go tools
$(GO) mod download $(TOOLS_MOD)
2 changes: 1 addition & 1 deletion _examples/proxy/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module example

go 1.25.10
go 1.26.8

require github.com/appleboy/easyssh-proxy v1.5.2

Expand Down
2 changes: 1 addition & 1 deletion _examples/scp/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module example

go 1.25.10
go 1.26.8

require github.com/appleboy/easyssh-proxy v1.5.2

Expand Down
2 changes: 1 addition & 1 deletion _examples/ssh/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module example

go 1.25.10
go 1.26.8

require github.com/appleboy/easyssh-proxy v1.5.2

Expand Down
2 changes: 1 addition & 1 deletion _examples/stream/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module example

go 1.25.10
go 1.26.8

require github.com/appleboy/easyssh-proxy v1.5.2

Expand Down
5 changes: 4 additions & 1 deletion _examples/stream/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ func main() {
}

// Call Run method with command you want to run on remote server.
stdoutChan, stderrChan, doneChan, errChan, err := ssh.Stream("for i in {1..5}; do echo ${i}; sleep 1; done; exit 2;", 60*time.Second)
stdoutChan, stderrChan, doneChan, errChan, err := ssh.Stream(
"for i in {1..5}; do echo ${i}; sleep 1; done; exit 2;",
60*time.Second,
)
// Handle errors
if err != nil {
panic("Can't run remote command: " + err.Error())
Expand Down
2 changes: 1 addition & 1 deletion _examples/writeFile/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module example

go 1.25.10
go 1.26.8

require github.com/appleboy/easyssh-proxy v1.5.2

Expand Down
52 changes: 40 additions & 12 deletions easyssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ var (
type Protocol string

const (
PROTOCOL_TCP Protocol = "tcp"
PROTOCOL_TCP4 Protocol = "tcp4"
PROTOCOL_TCP6 Protocol = "tcp6"
PROTOCOL_TCP Protocol = "tcp" //nolint:staticcheck // Preserve the exported name for API compatibility.
PROTOCOL_TCP4 Protocol = "tcp4" //nolint:staticcheck // Preserve the exported name for API compatibility.
PROTOCOL_TCP6 Protocol = "tcp6" //nolint:staticcheck // Preserve the exported name for API compatibility.
)

type (
Expand Down Expand Up @@ -161,7 +161,10 @@ func getSSHConfig(config DefaultConfig) (*ssh.ClientConfig, io.Closer) {
var signer ssh.Signer
var err error
if config.Passphrase != "" {
signer, err = sshkeys.ParseEncryptedPrivateKey([]byte(config.Key), []byte(config.Passphrase))
signer, err = sshkeys.ParseEncryptedPrivateKey(
[]byte(config.Key),
[]byte(config.Passphrase),
)
} else {
signer, err = ssh.ParsePrivateKey([]byte(config.Key))
}
Expand All @@ -182,7 +185,11 @@ func getSSHConfig(config DefaultConfig) (*ssh.ClientConfig, io.Closer) {
if config.UseInsecureCipher {
c.SetDefaults()
c.Ciphers = append(c.Ciphers, "aes128-cbc", "aes192-cbc", "aes256-cbc", "3des-cbc")
c.KeyExchanges = append(c.KeyExchanges, "diffie-hellman-group-exchange-sha1", "diffie-hellman-group-exchange-sha256")
c.KeyExchanges = append(
c.KeyExchanges,
"diffie-hellman-group-exchange-sha1",
"diffie-hellman-group-exchange-sha256",
)
}

if len(config.Ciphers) > 0 {
Expand Down Expand Up @@ -259,7 +266,11 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, *ssh.Client, error) {
defer func() { _ = closer.Close() }()
}

proxyClient, err := ssh.Dial(string(ssh_conf.Proxy.Protocol), net.JoinHostPort(ssh_conf.Proxy.Server, ssh_conf.Proxy.Port), proxyConfig)
proxyClient, err := ssh.Dial(
string(ssh_conf.Proxy.Protocol),
net.JoinHostPort(ssh_conf.Proxy.Server, ssh_conf.Proxy.Port),
proxyConfig,
)
if err != nil {
return nil, nil, err
}
Expand All @@ -280,7 +291,10 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, *ssh.Client, error) {

connCh := make(chan connResult, 1)
go func() {
conn, err := proxyClient.Dial(string(ssh_conf.Protocol), net.JoinHostPort(ssh_conf.Server, ssh_conf.Port))
conn, err := proxyClient.Dial(
string(ssh_conf.Protocol),
net.JoinHostPort(ssh_conf.Server, ssh_conf.Port),
)
select {
case connCh <- connResult{conn: conn, err: err}:
// Successfully sent result
Expand All @@ -307,7 +321,11 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, *ssh.Client, error) {
return nil, nil, err
}

ncc, chans, reqs, err := ssh.NewClientConn(conn, net.JoinHostPort(ssh_conf.Server, ssh_conf.Port), targetConfig)
ncc, chans, reqs, err := ssh.NewClientConn(
conn,
net.JoinHostPort(ssh_conf.Server, ssh_conf.Port),
targetConfig,
)
if err != nil {
_ = proxyClient.Close()
return nil, nil, err
Expand All @@ -320,7 +338,11 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, *ssh.Client, error) {
_ = proxyClient.Close()
}()
} else {
client, err = ssh.Dial(string(ssh_conf.Protocol), net.JoinHostPort(ssh_conf.Server, ssh_conf.Port), targetConfig)
client, err = ssh.Dial(
string(ssh_conf.Protocol),
net.JoinHostPort(ssh_conf.Server, ssh_conf.Port),
targetConfig,
)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -350,7 +372,10 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, *ssh.Client, error) {
// Stream returns one channel that combines the stdout and stderr of the command
// as it is run on the remote machine, and another that sends true when the
// command is done. The sessions and channels will then be closed.
func (ssh_conf *MakeConfig) Stream(command string, timeout ...time.Duration) (<-chan string, <-chan string, <-chan bool, <-chan error, error) {
func (ssh_conf *MakeConfig) Stream(
command string,
timeout ...time.Duration,
) (<-chan string, <-chan string, <-chan bool, <-chan error, error) {
// continuously send the command's output over the channel
stdoutChan := make(chan string)
stderrChan := make(chan string)
Expand Down Expand Up @@ -444,7 +469,10 @@ func (ssh_conf *MakeConfig) Stream(command string, timeout ...time.Duration) (<-
}

// Run command on remote machine and returns its stdout as a string
func (ssh_conf *MakeConfig) Run(command string, timeout ...time.Duration) (outStr string, errStr string, isTimeout bool, err error) {
func (ssh_conf *MakeConfig) Run(
command string,
timeout ...time.Duration,
) (outStr, errStr string, isTimeout bool, err error) {
stdoutChan, stderrChan, doneChan, errChan, err := ssh_conf.Stream(command, timeout...)
if err != nil {
// Check if the error is from a proxy dial timeout
Expand Down Expand Up @@ -547,7 +575,7 @@ func shellQuote(s string) string {
}

// Scp uploads sourceFile to remote machine like native scp console app.
func (ssh_conf *MakeConfig) Scp(sourceFile string, etargetFile string) error {
func (ssh_conf *MakeConfig) Scp(sourceFile, etargetFile string) error {
session, client, err := ssh_conf.Connect()
if err != nil {
return err
Expand Down
Loading
Loading