Last active
January 19, 2025 13:38
-
-
Save pschichtel/b6959a4897fcf0da1cc0ce638bec57fe to your computer and use it in GitHub Desktop.
A script to add an address to an alias in a pfSense firewall. The intended use is for fail2ban like tools.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from requests import Session | |
from re import findall | |
from argparse import ArgumentParser | |
parser = ArgumentParser() | |
parser.add_argument('--pfsense', type=str, metavar='address', required=True, help="Firewall base url") | |
parser.add_argument('--username', type=str, metavar='username', required=True, help="Firewall login username") | |
parser.add_argument('--password', type=str, metavar='password', required=True, help="Firewall login password") | |
parser.add_argument('--alias', type=str, metavar='alias id', required=True, help="The firewall alias ID (extract this from the alias URL)") | |
parser.add_argument('--listen', default=False, action='store_true', help="If true listens as an API server, otherwise reads from STDIN") | |
parser.add_argument('--listen-port', type=int, default=8080, help="The port to listen on if listen is set to true") | |
parser.add_argument('--reason', type=str, default="Spammed a node", help="The reason the given IPs get blocked") | |
def process_input(input_string): | |
base_url = args.pfsense | |
alias_edit_url = '/firewall_aliases_edit.php' | |
alias_list_url = '/firewall_aliases.php' | |
alias_id = args.alias | |
s = Session() | |
r = s.get(base_url, verify=False) | |
text = r.text | |
action = findall('<form id="iform"[^>]+?action="([^"]+)"', text)[0] | |
csrf_token = findall('name=\'__csrf_magic\'\s*value="([^"]+)"', text)[0] | |
login_payload = { | |
'__csrf_magic': csrf_token, | |
'usernamefld': args.username, | |
'passwordfld': args.password, | |
'login': 'Login' | |
} | |
s.post(base_url + action, data=login_payload, verify=False) | |
r = s.get(base_url + alias_edit_url + '?id=' + alias_id, verify=False) | |
text = r.text | |
csrf_token = findall('name=\'__csrf_magic\'.*?value="([^"]+)', text)[0] | |
alias_name = findall('name="origname".*?value="([^"]+)', text)[0] | |
alias_desc = findall('name="descr".*?value="([^"]+)', text)[0] | |
addresses = findall('name="(address\d+)".*?value="([^"]+)', text) | |
details = findall('name="(detail\d+)".*?value="([^"]+)', text) | |
alias_payload_base = { | |
'__csrf_magic': csrf_token, | |
'origname': alias_name, | |
'name': alias_name, | |
'id': alias_id, | |
'tab': 'ip', | |
'descr': alias_desc, | |
'type': 'host' | |
} | |
ips = set(findall('\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b', input_string)) | |
addr_count = len(addresses) | |
new_ids = [str(x) for x in range(addr_count, addr_count + len(ips))] | |
new_addresses = dict([("address" + i, addr) for (i, addr) in zip(new_ids, ips)]) | |
new_details = dict([("detail" + i, args.reason) for i in new_ids]) | |
alias_payload = { | |
**alias_payload_base, | |
**dict(addresses), | |
**dict(details), | |
**new_addresses, | |
**new_details | |
} | |
s.post(base_url + alias_edit_url, data=alias_payload, verify=False) | |
r = s.get(base_url + alias_list_url, verify=False) | |
csrf_token = findall('name=\'__csrf_magic\'.*?value="([^"]+)', r.text) | |
apply_payload = { | |
'__csrf_magic': csrf_token, | |
'apply': 'Apply changes', | |
'tab': 'ip' | |
} | |
r = s.post(base_url + alias_list_url, data=apply_payload, verify=False) | |
print(r.status_code) | |
args = parser.parse_args() | |
if args.listen: | |
from bottle import Bottle, request, run | |
app = Bottle() | |
@app.post('/block') | |
def block(): | |
print(app) | |
print(request) | |
process_input(request.body.getvalue().decode()) | |
run(app, port=args.listen_port) | |
else: | |
import sys | |
process_input(''.join(sys.stdin)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment