Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 0.6.12 #142

Merged
merged 11 commits into from
Aug 22, 2024
Merged
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
55 changes: 24 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -25,35 +25,22 @@ Supported multiple ssh proxy, http/socks5 proxy, x11 forward, and port forwardin
* Supported multiple proxy, **ssh**, **http**, and **socks5** proxy. It's supported multi-stage proxy.
* Supported **ssh-agent**.
* Supported **Local** and **Remote Port forward**, **Dynamic Forward(SOCKS5, http)**, **Reverse Dynamic Forward(SOCKS5, http)** and **x11 forward**.
* By using **NFS Forward**/**NFS Reverse Forward**, the NFS server starts listening to the PATH of the local host or remote machine, making it available via local port forwarding.
* Can use bashrc of local machine at ssh connection destination.
* It supports various authentication methods. Password, Public key, Certificate and PKCS11(Yubikey etc.).
* Can read the OpenSSH config (~/.ssh/config) and use it as it is.

## Demo

### run MacOSX

<p align="center">
<img src="./images/lssh_macosx.gif" />
</p>

### run Linux(Manjaro)

<p align="center">
<img src="./images/lssh_linux.gif" />
</p>

### run Windows(Windows 10)

<p align="center">
<img src="./images/lssh_windows.gif" />
</p>

## Install

### compile

compile gofile(tested go1.17.6).
compile gofile(tested go1.22.5).

GO111MODULE=auto go get -u github.com/blacknon/lssh/cmd/lssh
GO111MODULE=auto go get -u github.com/blacknon/lssh/cmd/lscp
@@ -104,11 +91,14 @@ option(lssh)

OPTIONS:
--host servername, -H servername connect servername.
--file filepath, -F filepath config filepath. (default: "/Users/uesugi/.lssh.conf")
--file filepath, -F filepath config filepath. (default: "/Users/blacknon/.lssh.conf")
-L [bind_address:]port:remote_address:port Local port forward mode.Specify a [bind_address:]port:remote_address:port. Only single connection works.
-R [bind_address:]port:remote_address:port Remote port forward mode.Specify a [bind_address:]port:remote_address:port. If only one port is specified, it will operate as Reverse Dynamic Forward. Only single connection works.
-D port Dynamic port forward mode(Socks5). Specify a port. Only single connection works.
-d port HTTP Dynamic port forward mode. Specify a port. Only single connection works.
-r port HTTP Reverse Dynamic port forward mode. Specify a port. Only single connection works.
-M port:/path/to/remote NFS Dynamic forward mode. Specify a port:/path/to/remote. Only single connection works.
-m port:/path/to/local NFS Reverse Dynamic forward mode. Specify a port:/path/to/local. Only single connection works.
-w Displays the server header when in command execution mode.
-W Not displays the server header when in command execution mode.
--not-execute, -N not execute remote command and shell.
@@ -118,7 +108,6 @@ option(lssh)
--parallel, -p run command parallel node(tail -F etc...).
--localrc use local bashrc shell.
--not-localrc not use local bashrc shell.
--pshell, -s use parallel-shell(pshell) (alpha).
--list, -l print server list from config.
--help, -h print this help
--version, -v print the version
@@ -127,7 +116,7 @@ option(lssh)
blacknon(blacknon@orebibou.com)

VERSION:
0.6.8
0.6.12

USAGE:
# connect ssh
@@ -139,6 +128,7 @@ option(lssh)
# run command parallel in selected server over ssh.
lssh -p command...


### lscpd

run command.
@@ -155,7 +145,7 @@ option(lscp)
OPTIONS:
--host value, -H value connect servernames
--list, -l print server list from config
--file value, -F value config file path (default: "/Users/uesugi/.lssh.conf")
--file value, -F value config file path (default: "/Users/blacknon/.lssh.conf")
--permission, -p copy file permission
--help, -h print this help
--version, -v print the version
@@ -164,7 +154,7 @@ option(lscp)
blacknon(blacknon@orebibou.com)

VERSION:
0.6.8
0.6.12

USAGE:
# local to remote scp
@@ -191,22 +181,21 @@ option(lsftp)
lsftp [options]

OPTIONS:
--file value, -F value config file path (default: "/Users/uesugi/.lssh.conf")
--file value, -F value config file path (default: "/Users/blacknon/.lssh.conf")
--help, -h print this help
--version, -v print the version

COPYRIGHT:
blacknon(blacknon@orebibou.com)

VERSION:
0.6.8
0.6.12

USAGE:
# start lsftp shell
lsftp



If you specify a command as an argument, you can select multiple hosts. Select host <kbd>Tab</kbd>, select all displayed hosts <kbd>Ctrl</kbd> + <kbd>a</kbd>.


@@ -592,12 +581,17 @@ Besides this, you can also specify ProxyCommand like OpenSSH.
Supported Local/Remote/Dynamic port forwarding.\
You can specify from the command line or from the configuration file.

When using NFS forward, lssh starts the NFS server and begins listening on the specified port.
After that, the forwarded PATH can be used as a mount point on the local machine or the remote machine.

#### command line option

lssh -L 8080:localhost:80 # local port forwarding
lssh -R 80:localhost:8080 # remote port forwarding
lssh -D 10080 # dynamic port forwarding
lssh -R 10080 # Reverse Dynamic port forwarding
lssh -L 8080:localhost:80 # local port forwarding
lssh -R 80:localhost:8080 # remote port forwarding
lssh -D 10080 # dynamic port forwarding
lssh -R 10080 # Reverse Dynamic port forwarding
lssh -M port:/path/to/remote # NFS Dynamic forward.
lssh -m port:/path/to/local # NFS Reverse Dynamic forward.

#### config file

@@ -632,17 +626,16 @@ You can specify from the command line or from the configuration file.
reverse_dynamic_port_forward = "11080"
note = "reverse dynamic forwawrd example"



If OpenSsh config is loaded, it will be loaded as it is.


</details>

## Related projects

- [go-sshlib](github.com/blacknon/go-sshlib)
- [lsshell](github.com/blacknon/lsshell)
- [go-sshlib](https://github.com/blacknon/go-sshlib)
- [lsshell](https://github.com/blacknon/lsshell)
- [lsmon](https://github.com/blacknon/lsmon)

## Licence

2 changes: 1 addition & 1 deletion cmd/lscp/args.go
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ USAGE:
app.Name = "lscp"
app.Usage = "TUI list select and parallel scp client command."
app.Copyright = "blacknon(blacknon@orebibou.com)"
app.Version = "0.6.11"
app.Version = "0.6.12"

// options
// TODO(blacknon): オプションの追加(0.7.0)
2 changes: 1 addition & 1 deletion cmd/lsftp/args.go
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ USAGE:
app.Name = "lsftp"
app.Usage = "TUI list select and parallel sftp client command."
app.Copyright = "blacknon(blacknon@orebibou.com)"
app.Version = "0.6.11"
app.Version = "0.6.12"

app.Flags = []cli.Flag{
cli.StringFlag{Name: "file,F", Value: defConf, Usage: "config file path"},
38 changes: 35 additions & 3 deletions cmd/lssh/args.go
Original file line number Diff line number Diff line change
@@ -59,11 +59,11 @@ USAGE:
app.Name = "lssh"
app.Usage = "TUI list select and parallel ssh client command."
app.Copyright = "blacknon(blacknon@orebibou.com)"
app.Version = "0.6.11"
app.Version = "0.6.12"

// TODO(blacknon): オプションの追加
// -m ... NFSマウントで、リモートホストの特定ディレクトリをローカルにマウント可能にする (v0.7.0)
// -M ... リバースNFSマウントで、リモートホストの特定ディレクトリをローカルにマウント可能にする (v0.7.0)
// -T ... マウント・リバースマウントのTypeを指定できるようにする(v0.7.0)
// ※ そもそもfuseをそのままfusemountでマウントできるのか?という謎もある
// -f ... バックグラウンドでの接続(X11接続やport forwardingをバックグラウンドで実行する場合など)。
// 「ssh -f」と同じ。 (v0.7.0)
// (https://github.com/sevlyar/go-daemon)
@@ -72,6 +72,8 @@ USAGE:
// ... 自動接続モード(接続が切れてしまった場合、自動的に再接続を試みる)。再試行の回数指定(デフォルトは3回?)。 (v0.7.0)
// --read_profile
// ... デフォルトではlocalrc読み込みでのshellではsshサーバ上のprofileは読み込まないが、このオプションを指定することで読み込まれるようになる (v0.7.0)
// -P
// ... 3muxを用いたマルチプレクサでのParallel Shell/Command実行を有効にする(v0.7.0)

// Set options
app.Flags = []cli.Flag{
@@ -85,6 +87,8 @@ USAGE:
cli.StringFlag{Name: "D", Usage: "Dynamic port forward mode(Socks5). Specify a `port`. Only single connection works."},
cli.StringFlag{Name: "d", Usage: "HTTP Dynamic port forward mode. Specify a `port`. Only single connection works."},
cli.StringFlag{Name: "r", Usage: "HTTP Reverse Dynamic port forward mode. Specify a `port`. Only single connection works."},
cli.StringFlag{Name: "M", Usage: "NFS Dynamic forward mode. Specify a `port:/path/to/remote`. Only single connection works."},
cli.StringFlag{Name: "m", Usage: "NFS Reverse Dynamic forward mode. Specify a `port:/path/to/local`. Only single connection works."},

// Other bool
cli.BoolFlag{Name: "w", Usage: "Displays the server header when in command execution mode."},
@@ -236,6 +240,34 @@ USAGE:
}
}

// Set NFS Forwarding
nfsForwarding := c.String("n")
if nfsForwarding != "" {
port, path, err := common.ParseNFSForwardPortPath(nfsForwarding)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}

r.NFSDynamicForwardPort = port
r.NFSDynamicForwardPath = path
}

// Set NFS Reverse Forwarding
nfsReverseForwarding := c.String("m")
if nfsReverseForwarding != "" {
port, path, err := common.ParseNFSForwardPortPath(nfsReverseForwarding)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}

path = common.GetFullPath(path)

r.NFSReverseDynamicForwardPort = port
r.NFSReverseDynamicForwardPath = path
}

// if err
if err != nil {
fmt.Printf("Error: %s \n", err)
29 changes: 29 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
@@ -152,6 +152,21 @@ func GetFullPath(path string) (fullPath string) {
usr, _ := user.Current()
fullPath = strings.Replace(path, "~", usr.HomeDir, 1)
fullPath, _ = filepath.Abs(fullPath)

// ファイルがシンボリックリンクかどうかを確認
info, err := os.Lstat(fullPath)
if err != nil {
fmt.Println("Error:", err)
return
}

// シンボリックリンクの場合、実体パスを取得
if info.Mode()&os.ModeSymlink != 0 {
realPath, err := filepath.EvalSymlinks(fullPath)
if err == nil {
fullPath = realPath
}
}
return fullPath
}

@@ -370,6 +385,20 @@ func ParseForwardPort(value string) (local, remote string, err error) {
return
}

// ParseNFSForwardPortPath
func ParseNFSForwardPortPath(value string) (port, path string, err error) {
data := strings.Split(value, ":")
if len(data) != 2 {
err = errors.New("Could not parse.")
return
}

port = data[0]
path = data[1]

return
}

// ParseHostPath return host and path, from host:/path/to/dir/file.
func ParseHostPath(value string) (host []string, path string) {
if !strings.Contains(value, ":") {
16 changes: 16 additions & 0 deletions conf/conf_struct_server.go
Original file line number Diff line number Diff line change
@@ -93,6 +93,22 @@ type ServerConfig struct {
// ex.) "11080"
HTTPReverseDynamicPortForward string `toml:"http_reverse_dynamic_port_forward"`

// NFS Dynamic Forward port setting
// ex.) "12049"
NFSDynamicForwardPort string `toml:"nfs_dynamic_forward"`

// NFS Dynamic Forward path setting
// ex.) "/path/to/remote"
NFSDynamicForwardPath string `toml:"nfs_dynamic_forward_path"`

// NFS Reverse Dynamic Forward port setting
// ex.) "12049"
NFSReverseDynamicForwardPort string `toml:"nfs_reverse_dynamic_forward"`

// NFS Reverse Dynamic Forward path setting
// ex.) "/path/to/local"
NFSReverseDynamicForwardPath string `toml:"nfs_reverse_dynamic_forward_path"`

// x11 forwarding setting
X11 bool `toml:"x11"`

8 changes: 8 additions & 0 deletions conf/openssh.go
Original file line number Diff line number Diff line change
@@ -80,6 +80,14 @@ func getOpenSSHConfig(path, command string) (config map[string]ServerConfig, err
Note: "from:" + ele,
}

if serverConfig.Addr == "" {
serverConfig.Addr = host
}

if serverConfig.User == "" {
serverConfig.User = os.Getenv("USER")
}

// TODO(blacknon): OpenSSSH設定ファイルだと、Certificateは複数指定可能な模様。ただ、あまり一般的な使い方ではないようなので、現状は複数のファイルを受け付けるように作っていない。
key := ssh_config.Get(host, "IdentityFile")
cert := ssh_config.Get(host, "Certificate")
18 changes: 14 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -13,11 +13,11 @@ require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect
github.com/blacknon/crypto11 v1.2.7 // indirect
github.com/blacknon/go-sshlib v0.1.15
github.com/blacknon/go-sshlib v0.1.16
github.com/blacknon/go-x11auth v0.1.0 // indirect
github.com/blacknon/textcol v0.0.1
github.com/c-bata/go-prompt v0.2.6
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dchest/bcrypt_pbkdf v0.0.0-20150205184540-83f37f9c154a // indirect
github.com/disiqueira/gotree v1.0.0
github.com/dustin/go-humanize v1.0.0
@@ -34,12 +34,12 @@ require (
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/nsf/termbox-go v1.1.1
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/sftp v1.13.4
github.com/pkg/sftp v1.13.6
github.com/pkg/term v1.2.0-beta.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/sevlyar/go-daemon v0.1.5
github.com/stretchr/testify v1.7.1
github.com/stretchr/testify v1.8.0
github.com/thales-e-security/pool v0.0.2 // indirect
github.com/urfave/cli v1.21.0
github.com/vbauerster/mpb v3.4.0+incompatible
@@ -50,5 +50,15 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

require (
github.com/blacknon/go-nfs-sshlib v0.0.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/rasky/go-xdr v0.0.0-20170124162913-1a41d1a06c93 // indirect
github.com/willscott/go-nfs-client v0.0.0-20240104095149-b44639837b00 // indirect
)

// replace
replace github.com/c-bata/go-prompt v0.2.6 => github.com/blacknon/go-prompt v0.2.7
Loading