我需要分析系统日志。我被告知我应该拆分列表,然后遍历它以找到一个IP地址。这只是日志的一小部分。有重复的条目因此我必须注意包含“从root用户输入密码”字样的行。
Jan 10 09:32:07 j4-be03 sshd[3876]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.241.173.35 user=root
Jan 10 09:32:09 j4-be03 sshd[3876]: Failed password for root from 218.241.173.35 port 47084 ssh2
Jan 10 09:32:17 j4-be03 sshd[3879]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.241.173.35 user=root
Jan 10 09:32:19 j4-be03 sshd[3879]: Failed password for root from 218.241.173.35 port 47901 ssh2
Jan 10 09:32:26 j4-be03 sshd[3881]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=218.241.173.35 user=root
Jan 10 09:32:29 j4-be03 sshd[3881]: Failed password for root from 218.241.173.35 port 48652 ssh2
到目前为止,这是我的代码,还有一些伪代码。
f=open('auth','r')
count=0
for line in f:
if "failed password for root from" in line:
count +=1
if count>=13:
take the ip address, remove duplicates and print the address
如果从一个IP地址尝试13次或更多次,则必须将此地址添加到文件中。我理解如何编写新文件,但是如果可能的话,一个小例子就会很方便。我熟悉.append
答案 0 :(得分:3)
可能更容易使用re
:
re_ips = r'Failed password for (?:root|invalid user\s?.*) from ((?:\d{1,3}\.){3}\d{1,3}) '
这将从相关行获取所有IP地址。下面是一个如何使用此正则表达式打印重复13次或更多次到文件bad_ips.log
的IP的示例:
from collections import defaultdict
import re
ip_freq = defaultdict(int)
with open("auth", "r") as fh:
for match in re.finditer(r'Failed password for (?:root|invalid user\s?.*) from ((?:\d{1,3}\.){3}\d{1,3}) ', fh.read()):
ip_freq[match.group(1)] += 1
with open("bad_ips.log", "w") as fh:
for ip, n in ip_freq.iteritems():
if n>=13:
print >>fh, ip
编辑根据您的新请求更新了正则表达式。
edit2:再次更新了正则表达式,以便在日志文件中正确匹配invalid user xxxx
。
edit3:整理了示例
答案 1 :(得分:1)
这应该可以解决问题:
import re
with open('auth', 'r') as f:
ip_list = re.findall(r'Failed password for root from (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', f.read()))
thirteen_plus = [i for i in set(ip_list) if ip_list.count(i) >= 13]
答案 2 :(得分:0)
你可以这样做:
import re
f = open('auth', 'r')
ip_list = re.findall(r'Failed password for root from (.*?)\s', f.read())
clean_list = [ip for ip in set(ip_list) if ip_list.count(ip) > 13]
你得到的clean_list
只包含auth
中重复次数超过13次的IP。
答案 3 :(得分:0)
好像你可以从那里获取split()
返回的列表中的第-4个元素来获取该IP地址。要计算某些地址的出现次数,您可以将它们添加到列表中并使用其count()
方法或创建某种计数字典(也有一些方便的类设计它,但你可以做一个常规字典)。
ip_count = {}
for line in open("auth"):
if "Failed password for root from" in line:
ip = line.split()[-4]
if ip in ip_count:
ip_count[ip] += 1
else:
ip_count[ip] = 1
然后你分析dict并将经常遇到的IP写入文件:
out = open("frequent.ips", 'w')
for ip in ip_count:
if ip_count[ip] > 13:
out.write("%s: %d attempts.\n" % (ip, ip_count[ip]))