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

win11下使用ProxyCommand指令会提示ssh: handshake failed,微软自带的openssh正常 #46

Closed
supersu097 opened this issue Oct 6, 2023 · 46 comments

Comments

@supersu097
Copy link

下面是我的config配置:

Host hetzner
  HostName x.x.x.x
  User xxx
  Port 22
  IdentityFile C:\Users\xxx\.ssh\id_rsa
  #ProxyCommand C:\Program Files (x86)\Nmap\ncat.exe --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p
  #ProxyCommand "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 %h %p

是我哪里使用的不对么,很奇怪微软自带的openssh客户端倒是正常

@supersu097
Copy link
Author

supersu097 commented Oct 6, 2023

 ✘  ~  ssh --debug
debug: C:\Users\xxx\.tssh.conf does not exist
debug: open config [C:\Users\xxx\.ssh\config] success
debug: decode config [C:\Users\xxx\.ssh\config] success
🍺 xxx
debug: will attempt key: C:\Users\xxx\.ssh\id_rsa ssh-rsa SHA256:xxxx
debug: add auth method: public key authentication
debug: add auth method: keyboard interactive authentication
debug: add auth method: password authentication
debug: login to [xxx], addr: x.x.x.x:22
debug: exec proxy command: "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 x.x.x.x 22
proxy command ["C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 x.x.x.x 22] new conn [x.x.x.x:22] failed: ssh: handshake failed: EOF

这是完整的debug信息,另外我试过把生成的私钥改成2048位的也还是报错,btw, 我把ProxyCommand指令注释掉tssh马上就正常可以连接了。

@lonnywong
Copy link
Member

1、目录含有空格时,前后加双引号试试,如 "C:\Program Files (x86)\Nmap\ncat.exe"
2、tssh 加个 --debug 参数,如 tssh --debug hetzner,看看输出的 proxy command 是什么。
3、然后手工执行 cmd /c "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 x.x.x.x 22 看看会输出什么?

@supersu097
Copy link
Author

supersu097 commented Oct 6, 2023

1、目录含有空格时,前后加双引号试试,如 "C:\Program Files (x86)\Nmap\ncat.exe" 2、tssh 加个 --debug 参数,如 tssh --debug hetzner,看看输出的 proxy command 是什么。 3、然后手工执行 cmd /c "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 x.x.x.x 22 看看会输出什么?

  1. 刚试了加了引号还是不行哈~
  2. --debug这个参数的输出在上面哈,我已经贴出来了
  3. SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4 只输出一个这个,然后就啥也没有了

@lonnywong
Copy link
Member

openssh 可以,也是用 ProxyCommand "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 %h %p 这个?

@supersu097
Copy link
Author

#ProxyCommand C:\Program Files (x86)\Nmap\ncat.exe --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p
#ProxyCommand "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 %h %p

ProxyCommand C:\Program Files (x86)\Nmap\ncat.exe --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p
ProxyCommand "C:\Users\xxx\bin\connect.exe" -S 127.0.0.1:7890 %h %p

在openssh下面,这两个都可以哈~

@lonnywong
Copy link
Member

没有双引号,并且路径名中没有空格,应该就可以。

@supersu097
Copy link
Author

supersu097 commented Oct 6, 2023

没有双引号,并且路径名中没有空格,应该就可以。

刚刚试了一下把空格和双引号都去掉了,现在正常了,哈哈,好神奇,什么原因~

@lonnywong
Copy link
Member

cmd = exec.Command("cmd", "/c", command)

含有双引号时,这行代码没有执行成功,我也还不知是什么原因。

lonnywong added a commit that referenced this issue Oct 6, 2023
@lonnywong
Copy link
Member

@supersu097 main 分支的代码应该支持双引号了。如果路径名含有空格,需要加上双引号。
( 路径名含有空格时,openssh 不加双引号也可以?tssh 在这种情况下是必须是加双引号的。 )

在下个版本发布前,可以自己编译,也可以这样安装( tssh.exeC:\Users\your_name\go\bin\ 下 ):

go install github.com/trzsz/trzsz-ssh/cmd/tssh@main

@supersu097
Copy link
Author

@supersu097 main 分支的代码应该支持双引号了。如果路径名含有空格,需要加上双引号。 ( 路径名含有空格时,openssh 不加双引号也可以?tssh 在这种情况下是必须是加双引号的。 )

在下个版本发布前,可以自己编译,也可以这样安装( tssh.exeC:\Users\your_name\go\bin\ 下 ):

go install github.com/trzsz/trzsz-ssh/cmd/tssh@main

@lonnywong 刚试了一下有空格的情况下,openssh加不加双引号都正常,tssh加或者不加都不行哈

@lonnywong
Copy link
Member

你是不是这样加的 "C:\Program Files (x86)\Nmap\ncat.exe" ?

@supersu097
Copy link
Author

你是不是这样加的 "C:\Program Files (x86)\Nmap\ncat.exe" ?

是的

@lonnywong
Copy link
Member

我测试是这样配置的 ProxyCommand "C:\Program Files (x86)\ssh.exe" -W %h:%p jumpserver,是可以的。

你用 go 编译下面这段代码,运行看输出什么?

package main

import (
	"fmt"
	"os/exec"
	"syscall"
)

func main() {
	// 把 %h 和 %p 替换成真实的 IP 和端口,tssh --debug 会看到替换的值。
	command := `"C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p`

	cmd := exec.Command("cmd.exe")
	cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf("/c %s", command)}

	var out, err bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &err

	if err := cmd.Run(); err != nil {
		fmt.Printf("err: %v\n", err)
	}

	fmt.Printf("stdout: %s\n", out.String())
	fmt.Printf("stderr: %s\n", err.String())
}

@supersu097
Copy link
Author

我测试是这样配置的 ProxyCommand "C:\Program Files (x86)\ssh.exe" -W %h:%p jumpserver,是可以的。

你用 go 编译下面这段代码,运行看输出什么?

package main

import (
	"fmt"
	"os/exec"
	"syscall"
)

func main() {
	// 把 %h 和 %p 替换成真实的 IP 和端口,tssh --debug 会看到替换的值。
	command := `"C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p`

	cmd := exec.Command("cmd.exe")
	cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf("/c %s", command)}

	var out, err bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &err

	if err := cmd.Run(); err != nil {
		fmt.Printf("err: %v\n", err)
	}

	fmt.Printf("stdout: %s\n", out.String())
	fmt.Printf("stderr: %s\n", err.String())
}

收到,我今天晚上下班后回家部署一下golang环境,然后直接go run一下应该也行是吧,或者我在wsl里面交叉编译一下,不想在宿主机器上再装golang了

@lonnywong
Copy link
Member

go run 是可以的,但 go run 是要安装 go 的。在 wsl 里交叉编译也可以( 会在当前目录输出 xxx.exe ):

GOOS=windows go build xxx.go

@supersu097
Copy link
Author

go run 是可以的,但 go run 是要安装 go 的。在 wsl 里交叉编译也可以( 会在当前目录输出 xxx.exe ):

GOOS=windows go build xxx.go

import bytes好像漏了,我加上去了,编译过去了,现在输出了下面的东西:

PS D:\> .\test.exe
stdout:
stderr: Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: 0 bytes sent, 0 bytes received in 1.22 seconds.

@lonnywong
Copy link
Member

手工执行那个命令,是输出什么呢?

@supersu097
Copy link
Author

手工执行那个命令,是输出什么呢?

手工执行那个带空格的完整路径的命令,ps会报语法错误,暂时不知道怎么解决,cd到那个路径下的输出如下:

PS C:\Program Files (x86)\Nmap> .\ncat.exe --verbose --proxy-type http --proxy 127.0.0.1:7890 x.x.x.x 22
Ncat: Version 7.94 ( https://nmap.org/ncat )
SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4
Invalid SSH identification string.
Ncat: 你的主机中的软件中止了一个已建立的连接。 .

@lonnywong
Copy link
Member

手工 "C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 x.x.x.x 22 这样执行会报错?

感觉 openssh 是没用上代理,但也没有报错,ssh -v hetzner 看看有没有输出 debug1: Executing proxy command: exec ...

@supersu097
Copy link
Author

手工 "C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 x.x.x.x 22 这样执行会报错?

感觉 openssh 是没用上代理,但也没有报错,ssh -v hetzner 看看有没有输出 debug1: Executing proxy command: exec ...

会报下面的错误:

所在位置 行:1 字符: 42
+ "C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http -- ...
+                                          ~~~~~~~
表达式或语句中包含意外的标记“verbose”。
所在位置 行:1 字符: 1
+ "C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http -- ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
“--”运算符仅适用于变量或属性。
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

ssh的输出里面表明走了代理:

debug1: Authenticator provider $SSH_SK_PROVIDER did not resolve; disabling
debug1: Executing proxy command: exec C:\\Program Files (x86)\\Nmap\\ncat.exe --verbose --proxy-type http --proxy 127.0.0.1:7890  x.x.x.x 22

@lonnywong
Copy link
Member

cmd 中执行 "C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 x.x.x.x 22 会怎样?

@lonnywong
Copy link
Member

更新一下测试代码( 正常应输出 stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4 ):

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"syscall"
	"time"
)

func main() {
	// 把 %h 和 %p 替换成真实的 IP 和端口,tssh --debug 会看到替换的值。
	command := `"C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p`

	cmd := exec.Command("cmd.exe")
	cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf("/c %s", command)}

	var out, err bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &err

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("timeout")
		if err := cmd.Process.Kill(); err != nil {
			fmt.Printf("kill error: %v\n", err)
		}
		fmt.Printf("stdout: %s\n", out.String())
		fmt.Printf("stderr: %s\n", err.String())
		os.Exit(0)
	}()

	if err := cmd.Run(); err != nil {
		fmt.Printf("run error: %v\n", err)
	}

	fmt.Printf("stdout: %s\n", out.String())
	fmt.Printf("stderr: %s\n", err.String())
}

@lonnywong
Copy link
Member

另一个测试:

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"time"

	"golang.org/x/sys/windows"
)

func main() {
	// 把 %h 和 %p 替换成真实的 IP 和端口,tssh --debug 会看到替换的值。
	command := `"C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p`

	argv, err := windows.DecomposeCommandLine(command)
	if err != nil {
		fmt.Printf("DecomposeCommandLine error: %v\n", err)
		return
	}
	for i, arg := range argv {
		fmt.Printf("argv[%d] = %v\r\n", i, arg)
	}

	cmd := exec.Command(argv[0], argv[1:]...)

	var outb, errb bytes.Buffer
	cmd.Stdout = &outb
	cmd.Stderr = &errb

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("timeout")
		if err := cmd.Process.Kill(); err != nil {
			fmt.Printf("kill error: %v\n", err)
		}
		fmt.Printf("stdout: %s\n", outb.String())
		fmt.Printf("stderr: %s\n", errb.String())
		os.Exit(0)
	}()

	if err := cmd.Run(); err != nil {
		fmt.Printf("run error: %v\n", err)
	}

	fmt.Printf("stdout: %s\n", outb.String())
	fmt.Printf("stderr: %s\n", errb.String())
}

@supersu097
Copy link
Author

cmd 中执行 "C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 x.x.x.x 22 会怎样?

你是说这种命令不兼容powershell是吗,晚点我试一下cmd

@supersu097
Copy link
Author

上面两个新的测试代码,我晚点编译一下试试

@supersu097
Copy link
Author

更新一下测试代码( 正常应输出 stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4 ):

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"syscall"
	"time"
)

func main() {
	// 把 %h 和 %p 替换成真实的 IP 和端口,tssh --debug 会看到替换的值。
	command := `"C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p`

	cmd := exec.Command("cmd.exe")
	cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf("/c %s", command)}

	var out, err bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &err

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("timeout")
		if err := cmd.Process.Kill(); err != nil {
			fmt.Printf("kill error: %v\n", err)
		}
		fmt.Printf("stdout: %s\n", out.String())
		fmt.Printf("stderr: %s\n", err.String())
		os.Exit(0)
	}()

	if err := cmd.Run(); err != nil {
		fmt.Printf("run error: %v\n", err)
	}

	fmt.Printf("stdout: %s\n", out.String())
	fmt.Printf("stderr: %s\n", err.String())
}

这个输出了下面的东西:

stdout:
stderr: Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: 0 bytes sent, 0 bytes received in 0.31 seconds.

@supersu097
Copy link
Author

另一个测试:

package main

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"time"

	"golang.org/x/sys/windows"
)

func main() {
	// 把 %h 和 %p 替换成真实的 IP 和端口,tssh --debug 会看到替换的值。
	command := `"C:\Program Files (x86)\Nmap\ncat.exe" --verbose --proxy-type http --proxy 127.0.0.1:7890 %h %p`

	argv, err := windows.DecomposeCommandLine(command)
	if err != nil {
		fmt.Printf("DecomposeCommandLine error: %v\n", err)
		return
	}
	for i, arg := range argv {
		fmt.Printf("argv[%d] = %v\r\n", i, arg)
	}

	cmd := exec.Command(argv[0], argv[1:]...)

	var outb, errb bytes.Buffer
	cmd.Stdout = &outb
	cmd.Stderr = &errb

	go func() {
		time.Sleep(3 * time.Second)
		fmt.Println("timeout")
		if err := cmd.Process.Kill(); err != nil {
			fmt.Printf("kill error: %v\n", err)
		}
		fmt.Printf("stdout: %s\n", outb.String())
		fmt.Printf("stderr: %s\n", errb.String())
		os.Exit(0)
	}()

	if err := cmd.Run(); err != nil {
		fmt.Printf("run error: %v\n", err)
	}

	fmt.Printf("stdout: %s\n", outb.String())
	fmt.Printf("stderr: %s\n", errb.String())
}

这一个输出如下:

PS D:\> .\test.exe
argv[0] = C:\Program Files (x86)\Nmap\ncat.exe
argv[1] = --verbose
argv[2] = --proxy-type
argv[3] = http
argv[4] = --proxy
argv[5] = 127.0.0.1:7890
argv[6] = x.x.x.x
argv[7] = 22
stdout:
stderr: Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: 0 bytes sent, 0 bytes received in 0.30 seconds.

@lonnywong
Copy link
Member

奇怪了,怎么都没有输出 stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4。感觉是 go 与 ncat.exe 不太兼容的样子。用 connect.exe 那个就可以?

@supersu097
Copy link
Author

奇怪了,怎么都没有输出 stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4。感觉是 go 与 ncat.exe 不太兼容的样子。用 connect.exe 那个就可以?

我晚点再用那个试一下,到时候我也加上空格试一下~

@supersu097
Copy link
Author

奇怪了,怎么都没有输出 stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4。感觉是 go 与 ncat.exe 不太兼容的样子。用 connect.exe 那个就可以?

换成connect.exe,现在正常了,如下:

PS D:\> .\test.exe
argv[0] = C:\Users\xxx\bin\tmp test\connect.exe
argv[1] = -S
argv[2] = 127.0.0.1:7890
argv[3] = x.x.x.x
argv[4] = 22
timeout
stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.4
stderr:

不过上面多出来一个timeout不知道是咋回事

@lonnywong
Copy link
Member

timeout是正常的

@lonnywong
Copy link
Member

@supersu097 你是要两个 proxycommand 同时运行, 还是只要运行一个?

@supersu097
Copy link
Author

@supersu097 你是要两个 proxycommand 同时运行, 还是只要运行一个?

任意一个就行,只要能连就行,不挑的🤣

@lonnywong
Copy link
Member

ncat 把 --proxy-type 改为 socks5 试试?

@supersu097
Copy link
Author

--proxy 127.0.0.1:7890

现在输出了下面的内容:

PS D:\> .\test.exe
argv[0] = C:\Program Files (x86)\Nmap\ncat.exe
argv[1] = --verbose
argv[2] = --proxy-type
argv[3] = socks5
argv[4] = --proxy
argv[5] = 127.0.0.1:7890
argv[6] =  x.x.x.x
argv[7] = 22
stdout:
stderr: Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Connected to proxy 127.0.0.1:7890
Ncat: No authentication needed.
Ncat: connection succeeded.
Ncat: 0 bytes sent, 0 bytes received in 0.32 seconds.

@lonnywong
Copy link
Member

看来 ncat 启动后很快就自动退出了,正常应该输出 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0,然后等待输入的。

@supersu097
Copy link
Author

看来 ncat 启动后很快就自动退出了,正常应该输出 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0,然后等待输入的。

手动在终端执行命令会出现等待输入的状态

@lonnywong
Copy link
Member

我自己安装了一个 ncat ,测试发现是可以的,结果:

argv[0] = ncat
argv[1] = --verbose
argv[2] = --proxy-type
argv[3] = socks5
argv[4] = --proxy
argv[5] = x.x.x.x:8090
argv[6] = x.x.x.x
argv[7] = 22
stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.3

stderr: Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Connected to proxy x.x.x.x:8090
Ncat: No authentication needed.
Ncat: connection succeeded.
Ncat: 0 bytes sent, 41 bytes received in 0.22 seconds.

@supersu097
Copy link
Author

我自己安装了一个 ncat ,测试发现是可以的,结果:

argv[0] = ncat
argv[1] = --verbose
argv[2] = --proxy-type
argv[3] = socks5
argv[4] = --proxy
argv[5] = x.x.x.x:8090
argv[6] = x.x.x.x
argv[7] = 22
stdout: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.3

stderr: Ncat: Version 7.94 ( https://nmap.org/ncat )
Ncat: Connected to proxy x.x.x.x:8090
Ncat: No authentication needed.
Ncat: connection succeeded.
Ncat: 0 bytes sent, 41 bytes received in 0.22 seconds.

哦哦,会不会是我电脑上装的火绒杀毒软件给拦截了呀,不过我不知道怎么设置白名单~

@lonnywong
Copy link
Member

临时退出它,再试试?

@supersu097
Copy link
Author

临时退出它,再试试?

刚退出了还是不行,我看网上有一篇博客说可能要彻底卸载火绒才行,我严重依赖了火绒的hips暂时不能卸载。

@lonnywong
Copy link
Member

还好,你有 connect.exe 那个可以用。没必要卸载啦。

openssh 居然能用 ncat 就很奇怪,你写一个错误的 ncat 命令,看 openssh 是不是还是成功的?

@supersu097
Copy link
Author

还好,你有 connect.exe 那个可以用。没必要卸载啦。

openssh 居然能用 ncat 就很奇怪,你写一个错误的 ncat 命令,看 openssh 是不是还是成功的?

现在崩了:

run error: exit status 2
stdout:
stderr: C:\Program Files (x86)\Nmap\ncat.exe: unrecognized option `--vverbose'
Ncat: Try `--help' or man(1) ncat for more information, usage options and help. QUITTING.

@lonnywong
Copy link
Member

你配置个错误的 ProxyCommand ,用 openssh 登录,看会不会失败?

@lonnywong
Copy link
Member

https://blog.panpili.com/2022/cloud/ssh-with-proxy/
我搜到这个,或者可以试试将 ncat 安装路径加入火绒保护区(没用过,我也不知怎么加,可以网上搜搜看)。

lonnywong added a commit that referenced this issue Oct 14, 2023
@lonnywong
Copy link
Member

tssh v0.1.12 已解决双引号的问题。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants