Using one time password with ssh.

本文介绍了一种通过使用一次性密码(OTP)来增强SSH登录安全性的方法。文章详细描述了如何安装并配置必要的软件包,如libpam-otpw,并调整sshd_config文件设置以启用Challenge Response验证。此外,还提供了重启SSH服务的方法及额外的安全建议。

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

With my host being public to internet, security now is the most concerning than it ever was.
So, first step, using one time password when login with ssh.

$ sudo apt-get install libpam-otpw

--- /etc/ssh/sshd_config ---
UsePrivilegeSeparation no
ChallengeResponseAuthentication yes
--- /etc/pam.d/sshd ---
#@include common-auth
auth required pam_otpw.so
session optional pam_otpw.so

~ $ optw-gen # Save the output!
$ sudo /etc/init.d/ssh restart

And here is some other tips:
http://www.ibm.com/developerworks/cn/aix/library/au-sshlocks/index.html?ca=drs-
我的代码如下,然后这个代码运行是能正常运行的,但我用pyinstaller进行打包pyinstaller --onefile \ --hidden-import=secrets \ --hidden-import=asyncio \ --hidden-import=oracledb.thin_impl \ --hidden-import=oracledb.base_impl \ --hidden-import=oracledb.constants \ --hidden-import=uuid \ test2.py ,打包之后的文件就显示oracle连接失败 #!/usr/bin/env python3 # -*- coding: utf-8 -*- import paramiko import re import sys import time import oracledb import traceback class NetworkInfoQuery: def __init__(self): # SSH connection settings self.aggregator_ip = '172.31.200.100' self.auth = { 'user': 'monitor', 'passwd': '#$12Bcl185Hadmin' } self.timeout = 25 self.buffer_size = 65535 self.device_type = None # Oracle database configuration self.db_config = { 'user': 'zhujh', 'password': 'zhujh20250422', 'host': '10.126.25.137', 'port': 1521, 'service_name': 'nodepdb1' } def decrement_ip(self, ip): """Decrement the last octet of an IPv4 address""" print(f"\n[DEBUG] Original WAN IP: {ip}") parts = list(map(int, ip.split('.'))) parts[-1] -= 1 adjusted_ip = '.'.join(map(str, parts)) print(f"[DEBUG] Adjusted WAN IP: {adjusted_ip}") return adjusted_ip # ========== SSH/Network Methods ========== def create_connection(self, host): """Establish SSH connection to network device""" print(f"\n[SSH] Connecting to {host}...") client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.connect( host, username=self.auth['user'], password=self.auth['passwd'], timeout=self.timeout ) print(f"[SSH] Connected to {host} successfully") return client except Exception as e: print(f"\n[SSH ERROR] Connection to {host} failed: {str(e)}") traceback.print_exc() sys.exit(1) def get_next_hop(self, target_ip): """Retrieve next hop from aggregation switch""" print("\n[PHASE 1] Querying aggregation switch routing table...") with self.create_connection(self.aggregator_ip) as conn: cmd = f"display ip routing-table {target_ip}" print(f"[CMD] Executing: {cmd}") _, stdout, stderr = conn.exec_command(cmd, get_pty=True) output = stdout.read().decode() + stderr.read().decode() print("[DEBUG] Parsing next hops...") hops = re.findall(r'\d+\.\d+\.\d+\.\d+(?=\s+\S+\s*$)', output, re.M) if hops: print(f"[RESULT] Next hops identified: {hops}") return hops[0] print("\n[ERROR] No valid next hop found in routing table") sys.exit(1) def retrieve_wan_ip(self, next_hop, target_ip): """Obtain WAN IP from head router""" self.device_type = None print(f"\n[PHASE 2] Connecting to head router {next_hop}...") with self.create_connection(self.aggregator_ip) as conn: channel = conn.invoke_shell() channel.settimeout(30) print("[SSH] Starting interactive session...") output = self.handle_ssh_flow(channel, next_hop, target_ip) return self.parse_routing_output(output, self.device_type) def handle_ssh_flow(self, channel, next_hop, target_ip): """Manage SSH jump with corrected prompt sequence""" buffer = "" # Initiate SSH connection print(f"[SSH] Jumping to {next_hop}...") channel.send(f"ssh {next_hop}\n") buffer += self.wait_for_match(channel, ['Username:'], 10) # Send username print("[AUTH] Sending username...") channel.send(f"{self.auth['user']}\n") buffer += self.wait_for_match(channel, ['[Y/N]', 'Password:'], 10) # Handle authentication prompts if '[Y/N]' in buffer: print("[SSH] Handling key verification...") channel.send("y\n") time.sleep(1) buffer += self.wait_for_match(channel, ['[Y/N]'], 8) if '[Y/N]' in buffer: channel.send("y\n") time.sleep(1) buffer += self.wait_for_match(channel, ['Password:'], 5) # Send password print("[AUTH] Sending password...") time.sleep(0.5) channel.send(f"{self.auth['passwd']}\n") buffer += self.wait_for_match(channel, ['>', '#'], 10) last_line = buffer.split('\n')[-1].strip() if '>' in last_line: self.device_type = 'H3C' cmd = f"display ip routing-table {target_ip}\n" elif '#' in last_line: self.device_type = 'Ruijie' cmd = f"show ip route {target_ip}\n" else: print("\n[ERROR] Unable to determine device type from prompt") sys.exit(1) print(f"[DEVICE] Identified as {self.device_type} device") # Execute target command print(f"[CMD] Executing: {cmd.strip()}") time.sleep(0.5) channel.send(cmd) buffer += self.wait_for_match(channel, ['>', '#'], 10) # Terminate connection print("[SSH] Closing connection...") time.sleep(0.5) channel.send("quit\n") buffer += self.wait_for_match(channel, ['>'], 5) return buffer def wait_for_match(self, channel, triggers, timeout): """Wait for specified patterns in response""" buffer = "" start = time.time() print(f"[SSH] Waiting for triggers: {triggers}") while time.time() - start < timeout: if channel.recv_ready(): data = channel.recv(self.buffer_size).decode('utf-8', 'ignore') buffer += data print(f"[DEVICE] {data.strip()}") for trigger in triggers: if trigger.lower() in data.lower(): print(f"[SSH] Trigger matched: {trigger}") return buffer time.sleep(0.5) print("[WARNING] Trigger timeout reached") return buffer def parse_routing_output(self, output, device_type): """Extract valid WAN IP from routing table""" print("\n[DEBUG] Parsing routing table output...") valid_ips = [] try: if device_type == 'H3C': pattern = r''' \b(\d+\.\d+\.\d+\.\d+/\d+) \s+(O_INTRA|Direct|O_INTER) \s+\d+\s+\d+\s+ (\d+\.\d+\.\d+\.\d+) \s+(?!InLoop)\S+ ''' matches = re.findall(pattern, output, re.VERBOSE) valid_ips = [match[2] for match in matches if match[2] != "127.0.0.1"] elif device_type == 'Ruijie': pattern = r''' Routing\s+Descriptor\s+Blocks:.*? (\d+\.\d+\.\d+\.\d+) ''' matches = re.findall(pattern, output, re.DOTALL | re.VERBOSE) valid_ips = [ip for ip in matches if ip != "0.0.0.0"] if valid_ips: print(f"[RESULT] Valid WAN IPs found: {valid_ips}") return valid_ips[0] except Exception as e: print(f"\n[PARSE ERROR] Routing table parsing failed: {str(e)}") traceback.print_exc() print("\n[ERROR] No valid WAN IP detected in routing output", f"\nDevice Type: {device_type}", f"\nOutput:\n{output}") sys.exit(1) # ========== Database Methods ========== def get_db_connection(self): """Create Oracle database connection without client""" print("\n[DATABASE] Connecting using Thin mode...") try: dsn = f"{self.db_config['host']}:{self.db_config['port']}/{self.db_config['service_name']}" conn = oracledb.connect( user=self.db_config['user'], password=self.db_config['password'], dsn=dsn, mode=THIN ) print("[DATABASE] Thin mode connection successful") return conn except Exception as e: print("\n[DATABASE ERROR] Connection failed:") print(f"Error Type: {type(e).__name__}") print(f"Details: {str(e)}") print("Troubleshooting:") print(f"1. Verify network connectivity to {self.db_config['host']}:{self.db_config['port']}") print("2. Check username/password validity") print("3. Validate service name configuration") traceback.print_exc() return None def query_network_info(self, head_ip): """Query network information by router IP""" print(f"\n[PHASE 3] Querying database for {head_ip}...") conn = self.get_db_connection() if not conn: return None cursor = None try: cursor = conn.cursor() sql = """ SELECT line_no, inst_name, inst_addr FROM repair.tb_line_wan WHERE router_ip = :1 """ print(f"[SQL] Executing query: {sql.strip()}") cursor.execute(sql, (head_ip,)) columns = [col[0].lower() for col in cursor.description] results = [dict(zip(columns, row)) for row in cursor] print(f"[RESULT] Found {len(results)} records") return results except oracledb.Error as e: print(f"\n[SQL ERROR] Query failed: {e}") traceback.print_exc() return None finally: if cursor: cursor.close() if conn: conn.close() def is_valid_ip(self, ip): """Validate IPv4 address""" if not re.match(r'^\d+\.\d+\.\d+\.\d+$', ip): print(f"[VALIDATION] Invalid IP format: {ip}") return False try: parts = list(map(int, ip.split('.'))) if all(0 <= p <= 255 for p in parts): return True print(f"[VALIDATION] IP octet out of range: {ip}") return False except ValueError: print(f"[VALIDATION] Invalid IP components: {ip}") return False # ========== Main Workflow ========== def get_network_info_by_local_ip(self, target_ip): """Main workflow: from local IP to network info""" print("\n" + "="*40) print(f"Starting query for {target_ip}") print("="*40) if not self.is_valid_ip(target_ip): print("\n[VALIDATION ERROR] Invalid IP address") return None try: # Phase 1: Get gateway IP print("\n=== Phase 1: Next Hop Query ===") gateway = self.get_next_hop(target_ip) # Phase 2: Get WAN IP print("\n=== Phase 2: WAN IP Retrieval ===") wan_ip = self.retrieve_wan_ip(gateway, target_ip) adjusted_wan_ip = self.decrement_ip(wan_ip) # Phase 3: Database Query print("\n=== Phase 3: Database Query ===") results = self.query_network_info(adjusted_wan_ip) return { 'target_ip': target_ip, 'head_ip': adjusted_wan_ip, 'network_info': results } except Exception as e: print(f"\n[CRITICAL ERROR] Process failed: {str(e)}") traceback.print_exc() sys.exit(1) def display_results(result): """Display query results""" if not result: print("\n[RESULT] No data returned from query") return print("\n" + "="*40) print("Final Results") print("="*40) if not result['network_info']: print(f"\nNo records found for WAN IP: {result['head_ip']}") return print(f"\nTarget IP: {result['target_ip']}") print(f"WAN Router IP: {result['head_ip']}") print(f"Found {len(result['network_info'])} record(s):") for idx, info in enumerate(result['network_info'], 1): print(f"\nRecord #{idx}:") print(f"Line Number: {info['line_no']}") print(f"Institution Name: {info['inst_name']}") print(f"Institution Address: {info['inst_addr']}") def get_user_input(): """Get IP address from user input""" print("\n" + "="*40) print("Network Information Query System") print("="*40) while True: try: target_ip = input("\nEnter LAN IP address: ").strip() if target_ip: return target_ip print("Invalid input: Empty value") except KeyboardInterrupt: print("\n\nOperation cancelled by user") sys.exit(0) if __name__ == "__main__": try: target_ip = get_user_input() query = NetworkInfoQuery() result = query.get_network_info_by_local_ip(target_ip) display_results(result) except Exception as e: print(f"\n[SYSTEM ERROR] Unexpected error: {str(e)}") traceback.print_exc() sys.exit(1) finally: print("\n" + "="*40) print("Query process completed") print("="*40 + "\n")
05-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值