连接CRT出现keyboard-interactive authentication with the ssh2 server failed解决方法

本文介绍了解决CRT连接中出现特定问题的方法。通过调整会话选项,取消勾选KeyboardInteractive选项,可以有效解决连接过程中的异常情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

连接CRT的时候出现以下情况:

解决步骤:

点击【选项】>> 【会话选项】 ,将Keyboard Interavtive这个选项勾选去掉,点击确定就可以了。

#include "FtSshTool.h" #include <libssh2.h> #include "FtSshChannel.h" #include <libssh2.h> #include <libssh2_sftp.h> #ifdef WIN32 #include <windows.h> #include <winsock2.h> #else #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <arpa/inet.h> #endif #include <sys/stat.h> #include <iostream> #include <string> #include <sys/types.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <ctype.h> #include <filesystem> #include <libssh2.h> #include <libssh2_sftp.h> #define _CRT_SECURE_NO_WARNINGS FtSshTool::FtSshTool(std::string srvIp, int srvPort) :m_srvIp(srvIp), m_srvPort(srvPort) { m_sock = -1; m_session = NULL; SetConsoleOutputCP(65001); //65001 是设置UTF编码 } FtSshTool::~FtSshTool(void) { Disconnect(); libssh2_exit(); } //void FtSshTool::S_KbdCallback(const char* name, int name_len, // const char* instruction, int instruction_len, // int num_prompts, // const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, // LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, // void** abstract) //{ // (void)name; // (void)name_len; // (void)instruction; // (void)instruction_len; // if (num_prompts == 1) // { // // responses[0].text = strdup(s_password.c_str()); // // responses[0].length = (int)s_password.size(); // } // (void)prompts; // (void)abstract; //} bool FtSshTool::Connect(std::string userName, std::string userPwd) { //WSAData wsdData; //int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData); //if (wsaRes != 0) //{ // printf("0000"); //} m_sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = inet_addr(m_srvIp.c_str()); if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { Disconnect(); return false; } // 初始化libssh2库 //flag 默认初始化选项 int rc = libssh2_init(0); m_session = libssh2_session_init(); if (libssh2_session_handshake(m_session, m_sock))//会话握手 { Disconnect(); return false; } // libssh2_session_set_blocking(m_session, 0); // 0非阻塞模式 1// 阻塞模式 int auth_pw = 0; std::string fingerprint = libssh2_hostkey_hash(m_session, LIBSSH2_HOSTKEY_HASH_SHA1); /* check what authentication methods are available */ std::string userauthlist = libssh2_userauth_list(m_session, userName.c_str(), (int)userName.size()); if (strstr(userauthlist.c_str(), "password") != NULL) { auth_pw |= 1; } if (strstr(userauthlist.c_str(), "keyboard-interactive") != NULL) { auth_pw |= 2; } if (strstr(userauthlist.c_str(), "publickey") != NULL) { auth_pw |= 4; } if (auth_pw & 1) { /* We could authenticate via password */ // 使用用户名和密码进行身份验证 if (libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str())) { Disconnect(); return false; } } else if (auth_pw & 2) { /* Or via keyboard-interactive */ // s_password = userPwd; /* if (libssh2_userauth_keyboard_interactive(m_session, userName.c_str(), &S_KbdCallback)) { Disconnect(); return false; }*/ } else { Disconnect(); return false; } return true; } int FtSshTool::Connect(std::string srvIp, std::string userName, std::string userPwd) { //WSAData wsdData; //int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData); //if (wsaRes != 0) //{ // printf("0000"); //} m_sock = socket(AF_INET, SOCK_STREAM, 0); if (m_sock < 0) { std::cerr << "Cannot create socket" << std::endl; return -5; } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = inet_addr(srvIp.c_str()); if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { std::cout << "connect Failed " << std::endl; Disconnect(); return -3; } // 初始化libssh2库 //flag 默认初始化选项 int rc = libssh2_init(0); if (rc != 0) { Disconnect(); return -1; // 初始化失败 } // 创建SSH会话 m_session = libssh2_session_init(); if (!m_session) { Disconnect(); return -2; // 创建会话失败 } // 设置会话选项 libssh2_session_set_blocking(m_session, 1);// 0非阻塞模式 1// 阻塞模式 libssh2_session_set_timeout(m_session,30*1000); // 连接到远程主机 rc = libssh2_session_startup(m_session, m_sock); if (rc != 0) { // 连接失败 Disconnect(); return -3; } // 使用用户名和密码进行身份验证(用户名和密码) rc = libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str()); if (rc != 0) { // 身份验证失败 libssh2_session_disconnect(m_session, "Authentication failed"); libssh2_session_free(m_session); Disconnect(); return -4; } return 0; } int FtSshTool::Connect(std::string localIp, std::string srvIp, std::string userName, std::string userPwd) { // 很重要,否则m_sock 创建失败 //WSAData wsdData; //int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData); //if (wsaRes != 0) //{ // printf("0000"); //} m_sock = socket(AF_INET, SOCK_STREAM, 0); sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(22); sin.sin_addr.s_addr = inet_addr(srvIp.c_str()); // 绑定客户端socket到特定的本地IP地址 struct sockaddr_in local_addr; memset(&local_addr, 0, sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(0); // 随机选择一个可用的本地端口 local_addr.sin_addr.s_addr = inet_addr(localIp.c_str()); // 客户端的本地IP地址 if (bind(m_sock, (struct sockaddr*)&local_addr, sizeof(local_addr)) == SOCKET_ERROR) { // std::cerr << "Bind failed" << std::endl; perror("Bind "); //return 1; } else { std::cout << "Bind Success" << localIp<< std::endl; } if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0) { perror("connect "); Disconnect(); return -3; } // 初始化libssh2库 //flag 默认初始化选项 int rc = libssh2_init(0); if (rc != 0) { Disconnect(); return -1; // 初始化失败 } // 创建SSH会话 m_session = libssh2_session_init(); if (!m_session) { Disconnect(); return -2; // 创建会话失败 } // 设置会话选项 libssh2_session_set_blocking(m_session, 1);// 0非阻塞模式 1// 阻塞模式 libssh2_session_set_timeout(m_session, 30 * 1000); // 连接到远程主机 rc = libssh2_session_startup(m_session, m_sock); if (rc != 0) { // 连接失败 Disconnect(); return -3; } // 使用用户名和密码进行身份验证(用户名和密码) rc = libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str()); if (rc != 0) { // 身份验证失败 libssh2_session_disconnect(m_session, "Authentication failed"); //libssh2_session_free(m_session); Disconnect(); return -4; } return 0; } bool FtSshTool::Disconnect(void) { //WSACleanup(); if (m_session) { libssh2_session_disconnect(m_session, "Bye bye, Thank you"); libssh2_session_free(m_session); m_session = NULL; } if (m_sock != -1) { #ifdef WIN32 closesocket(m_sock); #else close(m_sock); #endif m_sock = -1; } return true; } std::shared_ptr<Channel> FtSshTool::CreateChannel(const std::string& ptyType) { if (NULL == m_session) { return NULL; } LIBSSH2_CHANNEL* channel = NULL; /* Request a shell */ if (!(channel = libssh2_channel_open_session(m_session))) { return NULL; } /* Request a terminal with 'vanilla' terminal emulation * See /etc/termcap for more options */ if (libssh2_channel_request_pty(channel, ptyType.c_str())) { libssh2_channel_free(channel); return NULL; } /* Open a SHELL on that pty */ if (libssh2_channel_shell(channel)) { libssh2_channel_free(channel); return NULL; } std::shared_ptr < Channel> pChannel = std::make_shared<Channel>(channel); // Channel* ret = new Channel(channel); std::cout << pChannel->Read() << std::endl; return pChannel; } bool FtSshTool::Scp(std::string localfile, std::string remotefile) { FILE* local = NULL; int size = 0; try { struct stat file_info; size = std::filesystem::file_size(localfile); // Send the file struct stat file_status; // 获取文件状态 if (stat(localfile.c_str(), &file_status) == -1) { std::cerr << "Error: Unable to get file status for " << localfile << std::endl; return 1; } LIBSSH2_CHANNEL* channel = libssh2_scp_send64(m_session, remotefile.c_str(), 0644, size, file_status.st_mtime, file_status.st_atime); if (!channel) { char* errmsg; int errlen; int err = libssh2_session_last_error(m_session, &errmsg, &errlen, 0); fprintf(stderr, "Unable to open a session: (%d) %s\n", err, errmsg); } char mem[1024]; size_t nread; char* ptr; fprintf(stderr, "SCP session waiting to send file\n"); local = fopen(localfile.c_str(), "rb"); if (!local) { fprintf(stderr, "Cannot open local file %s\n", localfile.c_str()); return 1; } do { nread = fread(mem, 1, sizeof(mem), local); if (nread <= 0) { fclose(local); break; } ptr = mem; do { ssize_t nwritten; /* write the same data over and over, until error or completion */ nwritten = libssh2_channel_write(channel, ptr, nread); if (nwritten < 0) { fprintf(stderr, "ERROR %ld\n", (long)nwritten); break; } else { /* nwritten indicates how many bytes were written this time */ ptr += nwritten; nread -= (size_t)nwritten; } } while (nread); } while (1); if (local) fclose(local); libssh2_channel_send_eof(channel); fprintf(stderr, "Waiting for EOF\n"); libssh2_channel_wait_eof(channel); fprintf(stderr, "Waiting for channel to close\n"); libssh2_channel_wait_closed(channel); libssh2_channel_free(channel); channel = NULL; return true; } catch (...) { if (local) fclose(local); return false; } } bool FtSshTool::ScpAll(std::string localpath, std::string remotePath) { // 检查路径是否存在 if (!std::filesystem::exists(localpath)) { std::cerr << "Directory does not exist: " << localpath << std::endl; return false; } // 遍历文件夹中的所有项 for (const auto& entry : std::filesystem::directory_iterator(localpath)) { if (std::filesystem::is_directory(entry)) { } else { Scp(entry.path().string(), remotePath + "/"+ entry.path().filename().string()); } } return false; } bool FtSshTool::ScpDirectory(std::string localdirectory, std::string remotedirectory) { // 检查路径是否存在 if (!std::filesystem::exists(localdirectory)) { std::cerr << "Directory does not exist: " << localdirectory << std::endl; return false; } std::shared_ptr<Channel>pchannel = this->CreateChannel(); std::string cmd_cd = "mkdir -p " + remotedirectory; pchannel->Write(cmd_cd); // 遍历文件夹中的所有项 for (const auto& entry : std::filesystem::directory_iterator(localdirectory)) { if (std::filesystem::is_directory(entry)) { std::string cmd_cd = "mkdir -p " + remotedirectory + "/" + entry.path().filename().string(); pchannel->Write(cmd_cd); Scp(entry.path().string(), remotedirectory + "/" + entry.path().filename().string()); std::cout << cmd_cd << std::endl; } else { Scp(entry.path().string(), remotedirectory + "/" + entry.path().filename().string()); std::string cmd_cd = "cd "+ remotedirectory +"; chmod 777 -R ./*;"; pchannel->Write(cmd_cd); std::cout << cmd_cd << std::endl; } } return true; } bool FtSshTool::KillProcessByName(std::string processName) { // 构建完整的WinSCP命令 //std::string commandLine = mWinscpPath + " /command " // "open ssh://" + mUsername + ":" + mPassword + "@" + mHost + // "call ps -ef|grep " + processName + " |grep -v grep |awk '{print $2}'|xargs kill -2" // " /log=log.txt exit"; // 将执行结果保存到日志文件 //// 执行命令 //system(commandLine.c_str()); return true; } 是用scp方法的时候,libssh2_channel_write返回-39的错误原因
最新发布
07-01
<think>好的,我现在需要帮助用户解决Ubuntu 20.04中键盘交互式身份验证提示的问题。首先,用户提到参考的引用是关于Ubuntu 22.04升级后RSA密钥无法使用的问题,但用户现在的问题是关于Ubuntu 20.04的键盘交互式身份验证。我需要确认这两个问题是否有相关性,或者用户可能混淆了版本。 首先,键盘交互式身份验证(keyboard-interactive)通常与SSH服务的配置有关,可能涉及到PAM(Pluggable Authentication Modules)的设置。在Ubuntu系统中,SSH服务器的配置文件是/etc/ssh/sshd_config。用户可能遇到了在登录时被要求多次输入密码,或者不必要的提示,这通常与sshd_config中的设置有关。 可能的解决步骤包括: 1. 检查sshd_config中的ChallengeResponseAuthentication设置。如果设置为yes,SSH服务器会启用键盘交互式认证。如果用户希望禁用这种认证方式,可以将其设置为no。 2. 同样,检查PasswordAuthentication设置。如果用户希望使用密钥认证而非密码,应确保PasswordAuthentication为no,以避免密码提示。 3. 另一个相关参数是UsePAM。禁用PAM(UsePAM no)可能会影响某些认证方式,但需要谨慎处理,因为PAM管理多种认证模块。 4. 修改配置后需要重启SSH服务(systemctl restart sshd),以使更改生效。 5. 如果用户仍遇到问题,可能需要检查PAM配置文件,如/etc/pam.d/sshd,查看是否有模块导致额外的提示。 6. 日志文件(如/var/log/auth.log)可以提供更多线索,查看具体的认证失败原因。 需要提醒用户,在修改配置文件前备份原文件,避免配置错误导致无法登录。另外,如果用户同时使用密钥和密码,确保密钥认证优先,并确认权限设置正确(如~/.ssh目录权限为700,私钥为600)。 用户引用的参考内容是关于RSA密钥在升级后失效的问题,可能与此次问题无关,但可以注意是否升级过程中某些配置被覆盖,导致认证方式改变。例如,新版本的SSH可能默认禁用某些认证方法,但用户使用的是20.04,可能配置未被更改,但需要确认。 最后,生成相关问题需要考虑用户可能进一步的问题,比如如何设置密钥登录、如何调试SSH连接问题,或者如何处理PAM配置错误等。</think>### 解决Ubuntu 20.04键盘交互式身份验证提示的方法 在Ubuntu 20.04中,若SSH登录时频繁出现键盘交互式身份验证(`keyboard-interactive`)提示,通常与SSH服务配置或PAM(Pluggable Authentication Modules)设置相关。以下是分步解决方案: --- #### **步骤1:修改SSH服务配置** 1. 打开SSH配置文件: ```bash sudo nano /etc/ssh/sshd_config ``` 2. 调整以下参数: ```bash # 禁用键盘交互式认证 ChallengeResponseAuthentication no # 关闭密码认证(若已使用密钥认证) PasswordAuthentication no # 确保PAM模块配置合理 UsePAM yes ``` 3. 重启SSH服务: ```bash sudo systemctl restart ssh ``` --- #### **步骤2:检查PAM配置** 若问题仍未解决,可能与PAM规则冲突: 1. 编辑PAM的SSH配置文件: ```bash sudo nano /etc/pam.d/sshd ``` 2. 注释掉可能触发交互的模块(如`pam_google_authenticator.so`或其他两步验证工具)。 --- #### **步骤3:验证日志** 查看SSH登录日志以定位问题: ```bash sudo tail -f /var/log/auth.log ``` 若日志显示类似`"pam_unix(sshd:auth): authentication failure"`,需检查用户密码或密钥权限[^1]。 --- #### **步骤4:确保密钥权限正确** 若使用密钥认证: 1. 客户端私钥权限应为`600`: ```bash chmod 600 ~/.ssh/id_rsa ``` 2. 服务器公钥文件权限应为`644`: ```bash chmod 644 ~/.ssh/authorized_keys ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值