openproxyherder/scripts/dronebl/dronebl_check_tickets.py

136 lines
5.5 KiB
Python

import email
import logging
import psycopg2
import requests
import smtplib
import time
import yaml
from bs4 import BeautifulSoup
from datetime import datetime
config = yaml.full_load(open("config.yaml"))
pgconn = psycopg2.connect(dbname=config["dbname"], user=config["dbuser"], password=config["dbpassword"], host=config["dbhost"])
key = config["dronebl_key"]
entries_to_remove = []
smtp_connection = smtplib.SMTP(config["email_host"], config["email_port"])
smtp_connection.starttls()
smtp_connection.login(config["email_username"], config["email_password"])
debug_log = logging.getLogger("dronebl_check_tickets")
debug_log.setLevel(logging.DEBUG)
debug_log_file_handler = logging.FileHandler("dronebl_check_tickets_debug.log")
debug_log_file_handler.setLevel(logging.DEBUG)
debug_log.addHandler(debug_log_file_handler)
debug_log.debug(f"Current run at {datetime.now()}")
s = requests.Session()
headers = {"User-Agent": config["user_agent"]}
def send_active_email(ticket, details, comment):
msg = email.message.EmailMessage()
msg["From"] = config["email_from"]
msg["Date"] = email.utils.localtime()
if config.get("email_bcc"):
msg["Bcc"] = config["email_bcc"]
msg["Message-ID"] = email.utils.make_msgid(domain=config["email_domain"])
msg["To"] = ticket["email"]
msg["Subject"] = f"DroneBL removal request for {ticket['ip']} denied"
msg.set_content(config["email_active"].format(ticket["ip"], details, comment))
smtp_connection.send_message(msg)
def send_inactive_email(ticket, comment):
msg = email.message.EmailMessage()
msg["From"] = config["email_from"]
msg["Date"] = email.utils.localtime()
if config.get("email_bcc"):
msg["Bcc"] = config["email_bcc"]
msg["Message-ID"] = email.utils.make_msgid(domain=config["email_domain"])
msg["To"] = ticket["email"]
msg["Subject"] = f"DroneBL entry for {ticket['ip']} removed"
msg.set_content(config["email_inactive"].format(ticket["ip"], comment))
smtp_connection.send_message(msg)
def remove_dronebl_entries(entries):
request = "\n".join(entries)
request_string = f'<?xml version="1.0"?>\n<request key="{key}">\n{request}\n</request>'
headers = {
"Content-Type": "text/xml",
"Content-Length": str(len(request_string)),
}
debug_log.debug(request_string)
r = requests.post("https://eu1.dronebl.org/RPC2", data=request_string, headers=headers)
debug_log.debug(r.text)
def get_ticket_data():
login_form = {"ref": "https://eu1.dronebl.org/admin/tickets", "account": config["dronebl_account_name"], "password": config["dronebl_account_password"]}
r = s.post("https://eu1.dronebl.org/admin/login", headers=headers, data=login_form)
html = BeautifulSoup(r.text, "html5lib")
tickets = html.select(".listing2 > tbody > tr")
ticket_array = []
for ticket in tickets:
ticket_data = ticket.find_all("td")
ticket_array.append({
"ticket_id": ticket_data[0].text,
"incident_id": ticket_data[1].text,
"ip": ticket_data[2].text,
"proxy_type": ticket_data[3].text,
"port": ticket_data[4].text,
"date_submitted": ticket_data[5].text,
"name": ticket_data[6].text,
"email": ticket_data[7].text,
})
return ticket_array
with pgconn:
with pgconn.cursor() as curs:
for ticket in get_ticket_data():
ip = ticket["ip"]
curs.execute("select id,ip,port,exit_ip,status,proxy_type,last_seen,recheck from proxies where ip=%s or exit_ip=%s", (ip, ip))
should_remove = True
results = curs.fetchall()
comment = s.post("https://eu1.dronebl.org/admin/tickets", headers=headers, data={"ajax": "comments", "id": ticket["ticket_id"]})
debug_log.debug(comment.text)
already_sent = False
for entry in results:
debug_log.debug(results)
if not entry[7]:
curs.execute("update proxies set status='unscanned', recheck=true where id=%s", (entry[0],))
debug_log.debug(f"rechecking {ip}")
should_remove = False
else if entry[4] in ["scanning", "unscanned"]:
debug_log.debug(f"IP: {ip} is {entry[4]}, skipping")
should_remove = False
else if entry[4] == "active":
should_remove = False
if entry[1] == entry[3] or entry[1] == ip:
if entry[5] in ["http", "socks5", "socks4", "httpsocks", "https"]:
details = f"{entry[1]} has an open {entry[5]} proxy on port {entry[2]}, confirmed active at {entry[6]}"
if entry[5] == "vpngate":
details = f"{entry[1]} is running an open VPNGate proxy on port {entry[2]}, confirmed active at {entry[6]}. These are heavily abused by spammers, therefore they are blocked."
else:
details = f"Confirmed open {entry[5]} proxy with an entry IP of {entry[1]}, port {entry[2]} and exit IP of {entry[3]}, confirmed active at {entry[6]}"
debug_log.debug(details)
s.post("https://eu1.dronebl.org/admin/tickets", headers=headers, data={"ajax": "delete", "id": ticket["ticket_id"]})
if not already_sent:
send_active_email(ticket, details, comment.text)
debug_log.debug(f"Sent email: {details}")
already_sent = True
curs.execute("update proxies set recheck=false where id=%s", (entry[0],))
if should_remove:
if not results:
debug_log.debug(f"IP: {ip} is not in database")
else:
debug_log.debug(f"IP: {ip} has all inactive proxies")
incident_id = ticket["incident_id"]
entries_to_remove.append(f'<remove id="{incident_id}" />')
curs.execute("update proxies set recheck=false where ip=%s or exit_ip=%s", (ip, ip))
curs.execute("delete from dronebl where ip=%s", (ip,))
pgconn.commit()
send_inactive_email(ticket, comment.text)
time.sleep(5)
smtp_connection.quit()
if entries_to_remove:
remove_dronebl_entries(entries_to_remove)