Skip to content

Commit 389b034

Browse files
committed
add: [pdns-import]# pdns-import is a simple import from Passive DNS cof format (in an array) and import these back into a Passive DNS back-end
1 parent 853e114 commit 389b034

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed

bin/pdns-import.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/usr/bin/env python3
2+
#
3+
# pdns-import is a simple import from Passive DNS cof format (in an array)
4+
# and import these back into a Passive DNS backend
5+
#
6+
# This software is part of the D4 project.
7+
#
8+
# The software is released under the GNU Affero General Public version 3.
9+
#
10+
# Copyright (c) 2019 Alexandre Dulaunoy - [email protected]
11+
# Copyright (c) Computer Incident Response Center Luxembourg (CIRCL)
12+
13+
14+
import re
15+
import redis
16+
import fileinput
17+
import json
18+
import configparser
19+
import time
20+
import logging
21+
import sys
22+
import argparse
23+
24+
parser = argparse.ArgumentParser(description='Import array of standard Passive DNS cof format into your Passive DNS server')
25+
parser.add_argument('--file', dest='filetoimport', help='JSON file to import')
26+
args = parser.parse_args()
27+
28+
config = configparser.RawConfigParser()
29+
config.read('../etc/analyzer.conf')
30+
31+
expirations = config.items('expiration')
32+
excludesubstrings = config.get('exclude', 'substring').split(',')
33+
myuuid = config.get('global', 'my-uuid')
34+
myqueue = "analyzer:8:{}".format(myuuid)
35+
mylogginglevel = config.get('global', 'logging-level')
36+
logger = logging.getLogger('pdns ingestor')
37+
ch = logging.StreamHandler()
38+
if mylogginglevel == 'DEBUG':
39+
logger.setLevel(logging.DEBUG)
40+
ch.setLevel(logging.DEBUG)
41+
elif mylogginglevel == 'INFO':
42+
logger.setLevel(logging.INFO)
43+
ch.setLevel(logging.INFO)
44+
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
45+
ch.setFormatter(formatter)
46+
logger.addHandler(ch)
47+
48+
logger.info("Starting and using FIFO {} from D4 server".format(myqueue))
49+
50+
d4_server = config.get('global', 'd4-server')
51+
r = redis.Redis(host="127.0.0.1",port=6400)
52+
r_d4 = redis.Redis(host=d4_server.split(':')[0], port=d4_server.split(':')[1], db=2)
53+
54+
55+
with open('../etc/records-type.json') as rtypefile:
56+
rtype = json.load(rtypefile)
57+
58+
dnstype = {}
59+
60+
stats = True
61+
62+
for v in rtype:
63+
dnstype[(v['type'])] = v['value']
64+
65+
while (True):
66+
expiration = None
67+
if not (args.filetoimport):
68+
parser.print_help()
69+
sys.exit(0)
70+
with open(args.filetoimport) as dnsimport:
71+
records = json.load(dnsimport)
72+
73+
print (records)
74+
if records is False:
75+
logger.debug('Parsing of passive DNS line failed: {}'.format(l.strip()))
76+
continue
77+
for rdns in records:
78+
logger.debug("parsed record: {}".format(r))
79+
if 'rrname' not in rdns:
80+
logger.debug('Parsing of passive DNS line is incomplete: {}'.format(l.strip()))
81+
continue
82+
if rdns['rrname'] and rdns['rrtype']:
83+
rdns['type'] = dnstype[rdns['rrtype']]
84+
rdns['v'] = rdns['rdata']
85+
excludeflag = False
86+
for exclude in excludesubstrings:
87+
if exclude in rdns['rrname']:
88+
excludeflag = True
89+
if excludeflag:
90+
logger.debug('Excluded {}'.format(rdns['rrname']))
91+
continue
92+
if rdns['type'] == '16':
93+
rdns['v'] = rdns['v'].replace("\"", "", 1)
94+
query = "r:{}:{}".format(rdns['rrname'],rdns['type'])
95+
logger.debug('redis sadd: {} -> {}'.format(query,rdns['v']))
96+
r.sadd(query, rdns['v'])
97+
res = "v:{}:{}".format(rdns['v'], rdns['type'])
98+
logger.debug('redis sadd: {} -> {}'.format(res,rdns['rrname']))
99+
r.sadd(res, rdns['q'])
100+
101+
firstseen = "s:{}:{}:{}".format(rdns['rrname'], rdns['v'], rdns['type'])
102+
if not r.exists(firstseen):
103+
r.set(firstseen, rdns['time_first'])
104+
logger.debug('redis set: {} -> {}'.format(firstseen, rdns['time_first']))
105+
106+
107+
lastseen = "l:{}:{}:{}".format(rdns['rrname'], rdns['v'], rdns['type'])
108+
last = r.get(lastseen)
109+
if last is None or int(last) < int(rdns['timestamp']):
110+
r.set(lastseen, rdns['time_last'])
111+
logger.debug('redis set: {} -> {}'.format(lastseen, rdns['time_last']))
112+
113+
occ = "o:{}:{}:{}".format(rdns['rrname'], rdns['v'], rdns['type'])
114+
r.set(occ, rdns['count'])
115+
116+
117+
if stats:
118+
r.incrby('stats:processed', amount=1)
119+
if not r:
120+
logger.info('empty passive dns record')
121+
continue

0 commit comments

Comments
 (0)