Python - 拆分列表然后循环查找IP地址

时间:2012-03-11 00:10:08

标签: python

我需要分析系统日志。我被告知我应该拆分列表,然后遍历它以找到一个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

4 个答案:

答案 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]))