如何用Python提取SSH预认证横幅MAC地址及PuTTY端读取方法?
从SSH预认证横幅提取MAC地址的解决方案
一、Python实现方案
预认证横幅是SSH握手阶段服务器主动发送的消息,无需完成登录即可获取。可以用paramiko库实现:
步骤1:安装依赖
pip install paramiko
步骤2:提取代码示例
import paramiko import re def get_mac_from_ssh_banner(host, port=22): transport = None try: # 初始化SSH传输层,建立握手连接 transport = paramiko.Transport((host, port)) transport.start_client() # 获取预认证横幅(处理编码兼容问题) banner_data = transport.get_banner() if not banner_data: return None banner = banner_data.decode('utf-8', errors='ignore') # 匹配MAC地址的正则(兼容:/-分隔格式,忽略大小写) mac_regex = re.compile(r'([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}', re.IGNORECASE) match = mac_regex.search(banner) return match.group() if match else None except Exception as e: print(f"连接失败: {str(e)}") return None finally: if transport and transport.is_active(): transport.close() # 使用示例 if __name__ == "__main__": target_host = "192.168.1.100" mac_addr = get_mac_from_ssh_banner(target_host) print(f"提取到的MAC地址: {mac_addr}" if mac_addr else "未在横幅中找到MAC")
说明
- 无需输入用户名/密码,仅通过SSH握手即可获取预认证横幅
- 正则兼容大小写,以及
:或-分隔的MAC格式 - 处理了编码异常,避免因设备横幅编码不一致导致的报错
二、PuTTY提取方案
PuTTY GUI本身不支持自动捕获输出,但可以用其命令行工具plink.exe实现自动提取,或手动复制:
1. 手动提取
打开PuTTY,输入设备IP和端口(默认22),连接后输入用户名,此时会显示预认证横幅,直接选中并复制其中的MAC地址即可。
2. 命令行自动提取
plink.exe是PuTTY的命令行版本,可捕获SSH会话输出并匹配MAC:
步骤1:准备plink.exe
确保plink.exe和PuTTY在同一目录,或已添加到系统环境变量。
步骤2:PowerShell/CMD命令示例
# 直接输出匹配到的MAC地址 plink.exe -ssh 192.168.1.100 -l admin -noagent -batch | findstr /r "[0-9A-Fa-f][0-9A-Fa-f][:-][0-9A-Fa-f][0-9A-Fa-f][:-][0-9A-Fa-f][0-9A-Fa-f][:-][0-9A-Fa-f][0-9A-Fa-f][:-][0-9A-Fa-f][0-9A-Fa-f][:-][0-9A-Fa-f][0-9A-Fa-f]"
步骤3:Python调用plink实现自动提取
import subprocess import re def extract_mac_via_plink(host, username): cmd = [ "plink.exe", "-ssh", host, "-l", username, "-noagent", "-batch" # 禁用交互模式,避免等待输入密码 ] try: # 捕获会话输出(stdout+stderr,部分设备会把横幅输出到stderr) result = subprocess.run(cmd, capture_output=True, text=True, timeout=10) combined_output = result.stdout + result.stderr # 匹配MAC地址 mac_regex = re.compile(r'([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}', re.IGNORECASE) match = mac_regex.search(combined_output) return match.group() if match else None except subprocess.TimeoutExpired: print("连接超时") return None except Exception as e: print(f"执行错误: {str(e)}") return None # 使用示例 if __name__ == "__main__": mac = extract_mac_via_plink("192.168.1.100", "admin") print(f"提取到的MAC地址: {mac}" if mac else "未找到MAC地址")
说明
-batch参数会让plink在需要密码时直接退出,但预认证横幅已在退出前输出,不影响提取- 部分设备会将横幅输出到标准错误流,因此需要同时捕获stdout和stderr
内容的提问来源于stack exchange,提问作者ThawZin
相关产品推荐
相关产品推荐

