需求说明
- 二进制文件,Linux常见操作系统支持
- 自动读取现有kown_host文件中的主机地址和端口
- 支持通过配置文件更新key
源码
import paramiko
import os
import argparse
# 重写的父类方法,用来解决22端口默认key写入格式为[xxx.xxx.xxx.xx]:22的问题
class CustomAutoAddPolicy(paramiko.MissingHostKeyPolicy):
def __init__(self):
self.host_keys = {}
def missing_host_key(self, client, hostname, key):
self.host_keys[hostname] = key
# 处理主机地址,仅保留IP地址
if ':' in hostname:
hostname = hostname.split(':')[0].strip('[]')
client._host_keys.add(hostname, key.get_base64(),key)
def connect(host, port):
# ecdsa-sha2-nistp256 ssh-ed25519 ssh-dss ssh-rsa ssh-ed25519常见这四种秘钥协商
# filename = os.path.expanduser("~/.ssh/known_hosts")
# if not os.path.exists(os.path.dirname(filename)):
# os.makedirs(os.path.dirname(filename))
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh_client.connect(hostname=host, port=port, username='root', password='xxx')
except Exception as e:
print(e)
return ssh_client
return ssh_client
# 去除重复行
def remove_duplicate_lines_inplace(file_path):
with open(file_path, 'r+') as file:
lines = file.readlines()
# 使用 set 去除重复行,并保持原有顺序
unique_lines = list(set(lines))
# 移动文件指针到文件开始,截断文件内容
file.seek(0)
file.truncate()
# 写入去重后的内容
file.writelines(unique_lines)
def write_konw(client,host):
filename = os.path.expanduser("~/.ssh/known_hosts")
del_ip(filename=filename,text_to_filter=host)
with open(filename, "a") as f:
for hostname, keys in client._host_keys.items():
for keytype, key in keys.items():
f.write(
"{} {} {}\n".format(
hostname, keytype, key.get_base64()
)
)
print(f'更新{hostname}秘钥成功')
def read_konw_host(filename="~/.ssh/known_hosts"):
with open(os.path.expanduser(filename),encoding='utf-8') as f:
try:
tmp_list = []
for line in f.readlines():
if line == '\n':
continue
if ':' in line:
line = line.split(' ')
info = line[0]
host = info.split(':')[0].strip('[]')
port = info.split(':')[1]
Pubkey_model = line[1]
key = line[2]
else:
line = line.split(' ')
host = line[0]
port = 22
Pubkey_model = line[1]
key = line[2]
tmp_list.append([host,port,Pubkey_model,key])
return tmp_list
except Exception as e:
print('其他错误,请检查原始文件格式是否正确')
def read_config(filename):
with open(os.path.expanduser(filename),encoding='utf-8') as f:
try:
tmp_list = []
for line in f.readlines():
line = line.split(' ')
host = line[0]
port = line[1]
tmp_list.append([host,port])
return tmp_list
except Exception as e:
print('其他错误,请检查配置文件格式是否正确')
def del_ip(filename, text_to_filter):
with open(filename, 'r+', encoding='utf-8') as file:
lines = file.readlines()
# 将文件指针移动到文件开头
file.seek(0)
# 过滤掉包含指定文本的行
filtered_lines = [line for line in lines if text_to_filter not in line]
print(filtered_lines)
# 将结果写回原文件
file.truncate()
file.writelines(filtered_lines)
def auto_flush_key_from_kown_host():
filename = os.path.expanduser("~/.ssh/known_hosts")
current_list = read_konw_host()
for i in current_list:
connect_object= connect(i[0],i[1])
host_keys = connect_object._host_keys
if len(host_keys) != 0:
for host, keys in host_keys.items():
for keytype, key in keys.items():
del_ip(filename=filename,text_to_filter=str(i[0]))
with open(file=filename,mode='a',encoding='utf-8') as f:
new_key =(f'{host} {keytype} {key.get_base64()}\n')
f.write(new_key)
print(f'更新{i[0]}密钥成功')
else:
print(f'更新{i[0]}密钥错误')
remove_duplicate_lines_inplace(filename)
def custom_config_reflush_key(config_file_name):
print(f'当前配置文件路径:{config_file_name}')
current_list = read_config(config_file_name)
filename = os.path.expanduser("~/.ssh/known_hosts")
for i in current_list:
connect_object= connect(i[0],int(i[1]))
host_keys = connect_object._host_keys
if host_keys:
for host, keys in host_keys.items():
for keytype, key in keys.items():
# print(f"Host: {host}")
# print(f"Key Type: {keytype}")
# print(f"Key: {key.get_base64()}")
del_ip(filename=filename,text_to_filter=str(i[0]))
with open(file=filename,mode='a',encoding='utf-8') as f:
new_key =(f'{host} {keytype} {key.get_base64()}\n')
f.write(new_key)
print(f'更新{i[0]}密钥成功')
else:
print(f'更新{i[0]}密钥错误')
remove_duplicate_lines_inplace(filename)
if __name__ == "__main__":
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description="SSH秘钥自动更新V1.0")
parser.description = """
SSH秘钥自动更新V1.0
使用方法:
1.默认模式:不添加任何参数,将自动从~/.ssh/known_hosts文件中读取IP地址和端口并自动更新密钥。
2.手动模式:指定host和port进行手动更新
3.配置模式:使用-f参数指定配置文件,配置文件正确格式为【IP 端口】的形式
"""
parser.add_argument("host", nargs="?", help="主机名称 or IP地址")
parser.add_argument("-port", type=int, default=22, help="SSH 服务端口 (default: 22)")
parser.add_argument("-f", type=str, help="读取文件")
args = parser.parse_args()
if args.host:
connect(args.host, args.port)
current_client_connect = connect(args.host, args.port)
write_konw(current_client_connect,host=args.host)
elif args.f:
print("配置模式:自动读取配置文件中的主机地址和端口然后更新key")
custom_config_reflush_key(config_file_name=args.f)
else:
print("默认模式:自动读取[know_host]文件并更新")
auto_flush_key_from_kown_host()
成品打包下载
见顶部资源绑定区
4799

被折叠的 条评论
为什么被折叠?



