这几天由于个人需要在Windows
系统上使用Gitea
搭建了一个代码仓库,考虑到Windows
没有很方便的SSH
服务就直接使用了Gitea
的内建SSH
。但是在使用Git Bash
里的git
直接访问代码仓库时会出现以下报错:
Cloning into 'test'...
git@127.0.0.1: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
网上直接搜了下这个报错信息,都是让给Gitea
增加SSH Keys
,但是我明明已经增加了正确的密钥。更关键的,如果是通过TortoiseGit
访问的话就是没有问题的。而Git Bash
里的git
访问GitHub
又是好用的,这就十分尴尬了。于是:
1. 从Gitea
日志中找有用信息
先Gitea
中的日志配置信息加详细:
[log]
MODE = file
LEVEL = trace
ROOT_PATH = D:/software/gitea/log
然后可以从日志中找到问题所在:
2021/11/26 15:38:27 modules/ssh/ssh.go:259:sshConnectionFailed() [W] Failed connection from 127.0.0.1:1037 with error: [ssh: no auth passed yet]
2021/11/26 15:38:27 modules/ssh/ssh.go:261:sshConnectionFailed() [W] Failed authentication attempt from 127.0.0.1:1037
2. 撸Gitea
源码找问题源头
ssh.go文件涉案源码如下:
// sshConnectionFailed logs a failed connection
// - this mainly exists to give a nice function name in logging
func sshConnectionFailed(conn net.Conn, err error) {
// Log the underlying error with a specific message
log.Warn("Failed connection from %s with error: %v", conn.RemoteAddr(), err)
// Log with the standard failed authentication from message for simpler fail2ban configuration
log.Warn("Failed authentication attempt from %s", conn.RemoteAddr())
}
// Listen starts a SSH server listens on given port.
func Listen(host string, port int, ciphers []string, keyExchanges []string, macs []string) {
srv := ssh.Server{
Addr: net.JoinHostPort(host, strconv.Itoa(port)),
PublicKeyHandler: publicKeyHandler,
Handler: sessionHandler,
ServerConfigCallback: func(ctx ssh.Context) *gossh.ServerConfig {
config := &gossh.ServerConfig{}
config.KeyExchanges = keyExchanges
config.MACs = macs
config.Ciphers = ciphers
return config
},
ConnectionFailedCallback: sshConnectionFailed,
// We need to explicitly disable the PtyCallback so text displays
// properly.
PtyCallback: func(ctx ssh.Context, pty ssh.Pty) bool {
return false
},
}
// ...
}
可见错误是从一个回调函数中报出来的,而这个回调则是Go
的原生模块ssh
里出错后调用的。
3. 再看Go
的锅
Go
官网被X,Google Code
也被X,百度搜索又啥都没有;不要紧,Bing国际版还是给力的,go ssh: no auth passed yet
的第一条结果就够用了:
Variables ¶
var ErrNoAuth = errors.New("ssh: no auth passed yet")
ErrNoAuth is the error value returned if no authentication method has been passed yet. This happens as a normal part of the authentication loop, since the client first tries 'none' authentication to discover available methods. It is returned in ServerAuthError.Errors from NewServerConn.
原来Go
的SSH
服务器不响应客户端未定义认证类型的请求。
4. 打完收功
这样就只能从ssh_config
下手了,在配置中增加:
Host 127.0.0.1
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa
世界瞬间美好了。