def main():
    print('Starting PfSense Parental Control App')

    print('Finding LAN devices')
    devices = find_devices()

    print('Finding Rule Overides')
    overrides = get_overrides()

    print('Finding blocked users')
    blocked = find_blocked(devices, overrides)

    print('Resolving IP addresses')
    blocked_ip = [[build_descr(b), devices.get(b['MAC'])] for b in blocked]

    print("Configuring Faux API")
    api = PfsenseFauxapi(PFSENSE_HOST, apikey, apisecret)
    api.proto = 'http'

    print("Requesting config")
    current_block_rules, default_rules = get_rules(api)
    current_block_ip = dict(
        (r['descr'], r['source']['address']) for r in current_block_rules)

    new_rules = build_new_rules(blocked_ip, current_block_ip)
    new_patch = create_filter_rule_patch(new_rules + default_rules)

    pprint.pprint(new_patch)
    print("patching")
    api.config_patch(new_patch)
    api.function_call({
        'function': 'filter_configure_sync',
        'args': [False],
        'includes': ['shaper.inc'],
    })
def test_function_call(mock_requests_post):

    fauxapi = PfsenseFauxapi(host=None, apikey=None, apisecret=None)
    mock_requests_post.return_value.status_code = 200
    mock_requests_post.return_value.text = '{"callid": "5c8dc7cda6948", "action": "function_call", "message": "ok", "data": {"return": {}}}'

    response = fauxapi.function_call(None)
    assert response['action'] == 'function_call'
    assert response['message'] == 'ok'
Example #3
0
print(json.dumps(
    FauxapiLib.alias_update_urltables())
)

# # system reboot
# =============================================================================
# print(json.dumps(
#     FauxapiLib.system_reboot())
# )

# function_call - examples
# =============================================================================
print(json.dumps(
    FauxapiLib.function_call({
        'function': 'return_gateways_status',
        'args': [False]
    }
)))

print(json.dumps(
    FauxapiLib.function_call({
        'function': 'discover_last_backup'
    }
)))

print(json.dumps(
    FauxapiLib.function_call({
        'function': 'return_gateways_status',
        'includes': ['gwlb.inc']
    }
)))
Example #4
0
class PfSense:
    """
    PfSense Thingy...
    ...
    Methods
    -------
    get_openvpn_settings(self) -> dict:
    set_pfsense_config(self, data: dict, vpnid: list, refresh: bool = None) -> dict:
    get_pf_openvpn_clients(self) -> dict:
    get_pf_openvpn_locations(self, vpn_clients: dict) -> set:
    """
    def __init__(self):
        self.host = getenv("HOST_ADDRESS")
        self.port = 443
        self.key = getenv("FAUXAPI_KEY")
        self.secret = getenv("FAUXAPI_SECRET")
        try:
            PfsenseFauxapi(f"{self.host}:{self.port}", self.key, self.secret)
        except PfsenseFauxapiException as e:
            print(f"error: {str(e)}")
        else:
            self.pfapi = PfsenseFauxapi(f"{self.host}:{self.port}", self.key,
                                        self.secret)

    def get_openvpn_settings(self) -> dict:
        try:
            pf_openvpn_settings = self.pfapi.config_get('openvpn')
        except PfsenseFauxapiException as e:
            return {"error": str(e)}
        else:
            return pf_openvpn_settings

    def set_pfsense_config(self,
                           data: dict,
                           vpnid: list,
                           refresh: bool = None) -> dict:
        """
        Parameters
        ----------
        data : dict
            .
        vpnid : list
            .
        refresh : bool
            .
        """
        try:
            resp = self.pfapi.config_set(data, 'openvpn')
        except PfsenseFauxapiException as e:
            return {"error": str(e)}
        else:
            if refresh:
                self.pfapi.config_reload()
            if len(vpnid):
                for vid in vpnid:
                    data = self.pfapi.function_call({
                        "function":
                        "openvpn_restart_by_vpnid",
                        "args": ["client", f"{vid}"]
                    })
            return resp

    def get_pf_openvpn_clients(self) -> dict:
        clients: list = []
        vpn_clients = self.get_openvpn_settings()
        if "error" in vpn_clients.keys():
            return vpn_clients

        locations: set = self.get_pf_openvpn_locations(vpn_clients)
        for vpnclient in vpn_clients["openvpn-client"]:
            clients.append(vpnclient["server_addr"])

        return {"clients": clients, "locations": list(locations)}

    def get_pf_openvpn_locations(self, vpn_clients: dict) -> set:
        """
        Parameters
        ----------
        vpn_clients : dict
            .
        """
        locations = set()
        for client in vpn_clients["openvpn-client"]:
            loc = is_vpn_address(client["server_addr"])
            if loc is not None:
                locations.add(loc[1].lower())
        return locations
class pfSenseInfluxCollector:
	def __init__(self, config_file):
		"""Program to send pfSense information collected from FauxAPI to InfluxDB"""
		self.config = configparser.ConfigParser()
		self.config.read(config_file)
		self.fauxapi = PfsenseFauxapi(self.config['FAUXAPI']['APIHost'], self.config['FAUXAPI']['APIKey'], self.config['FAUXAPI']['APISecret'])
		self.influx_client = InfluxDBClient(host=self.config['INFLUXDB']['InfluxDBHost'], port=self.config['INFLUXDB']['Port'],
			username=self.config['INFLUXDB']['Username'], password=self.config['INFLUXDB']['Password'], database=self.config['INFLUXDB']['Database'])
		self.pfSense_config = self.fauxapi.config_get()
		self.pfSense_host = self.pfSense_config['system']['hostname'] + "." + self.pfSense_config['system']['domain']

	def run(self):
		"""Run enabled modules wuth delay as defined in config file"""
		threading.Timer(int(self.config['GENERAL']['Delay']), self.run).start()
		for function in self.module_dictionary:
			if self.config['MODULES'].getboolean(function):
				self.module_dictionary[function](self)

	def fauxapi_function_call(self, functionName):
		"""Call fauxapi function_call without function arguments"""
		data = {
			"function": functionName
		}
		return self.fauxapi.function_call(data)['data']['return']

	def fauxapi_function_call_args(self, functionName, args):
		"""Call fauxapi function_call function with arguments"""
		data = {
			"function": functionName,
			"args": args
		}
		return self.fauxapi.function_call(data)['data']['return']

	def write_influxdb_data(self, data):
		"""Write set of data to InfluxDB."""
		self.influx_client.write_points(data)

	def gateway_status(self):
		"""Get and save information about statuses of gateways."""
		gateways = self.fauxapi_function_call_args("return_gateways_status", "true")
		for gateway in gateways:
			gateway_status = 0 if gateways[gateway]['status'] == "down" else 1
			gateway_data = [
				{
					"measurement": "gateway_status",
					"fields": {
						"name": gateways[gateway]['name'],
						"rtt": gateways[gateway]['delay'],
						"rttsd": gateways[gateway]['stddev'],
						"status": gateway_status
					},
					"tags": {
						"host": self.pfSense_host
					}
				}
			]
			self.write_influxdb_data(gateway_data)

	def interface_statistics(self):
		"""Get and save information about interfaces statistics."""
		interface_descriptions = self.fauxapi_function_call("get_configured_interface_with_descr")
		for interface in interface_descriptions:
			interface_info = self.fauxapi_function_call_args("get_interface_info", interface)
			interface_data = [
				{
					"measurement": "interface_statistics",
					"fields": {
						"bytes_in": interface_info['inbytes'],
						"bytes_out": interface_info['outbytes'],
						"collisions": interface_info['collisions'],
						"errors_in": interface_info['inerrs'],
						"errors_out": interface_info['outerrs'],
						"name": interface_descriptions[interface],
						"packets_in": interface_info['inpkts'],
						"packets_out": interface_info['outpkts']
					},
					"tags": {
						"host": self.pfSense_host,
						"interface": interface_info['if']
					}
				}
			]
			self.write_influxdb_data(interface_data)

	def interface_status(self):
		"""Get and save information about statuses of interfaces."""
		interface_descriptions = self.fauxapi_function_call("get_configured_interface_with_descr")
		for interface in interface_descriptions:
			interface_info = self.fauxapi_function_call_args("get_interface_info", interface)
			interface_data = [
				{
					"measurement": "interface_status",
					"fields": {
						"ip_address": interface_info['ipaddr'],
						"name": interface_descriptions[interface],
						"status": 1 if interface_info['status'] == 'up' else 0
					},
					"tags": {
						"host": self.pfSense_host,
						"interface": interface_info['if']
					}
				}
			]
			self.write_influxdb_data(interface_data)

	def openvpn_client_status(self):
		"""Get and save information about OpenVPN clients."""
		for client in self.fauxapi_function_call("openvpn_get_active_clients"):
			client_data = [
				{
					"measurement": "openvpn_client_status",
					"fields": {
						"remote_host": client['remote_host'],
						"status": 1 if client['status'] == "up" else 0,
						"virtual_address": client['virtual_addr']
					},
					"tags": {
						"host": self.pfSense_host,
						"vpnid": int(client['vpnid']),
					}
				}
			]
			self.write_influxdb_data(client_data)

	def openvpn_connected_clients(self):
		"""Get and save information about connected clients to OpenVPN server."""
		for server in self.fauxapi_function_call("openvpn_get_active_servers"):
			server_name = server['name']
			for connection in server['conns']:
				connection_data = [
					{
						"measurement": "openvpn_connected_clients",
						"fields": {
							"client_id": int(connection['client_id']),
							"common_name": connection['common_name'],
							"remote_host": connection['remote_host'],
							"virtual_address": connection['virtual_addr']
						},
						"tags": {
							"host": self.pfSense_host,
							"server": server_name
						}
					}
				]
				self.write_influxdb_data(connection_data)
			connected_clients_data = [
				{
					"measurement": "openvpn_connected_clients",
					"fields": {
						"connected_clients": len(server['conns'])
					},
					"tags": {
						"host": self.pfSense_host,
						"server": server_name
					}
				}
			]
			self.write_influxdb_data(connected_clients_data)

	def services_status(self):
		"""Get and save information about statuses of services."""
		for service in self.fauxapi_function_call("get_services")[1:]:
			service_status = self.fauxapi_function_call_args("get_service_status", [service])
			service_data = [
				{
					"measurement": "services_status",
					"fields": {
						"description": service['description'],
						"status": 1 if service_status else 0
					},
					"tags": {
						"host": self.pfSense_host,
						"service": service['name']
					}
				}
			]
			self.write_influxdb_data(service_data)

	# Module Dictionary to allow dynamic calling of functions depending on config file
	module_dictionary = {"Gateway_Status": gateway_status, "Interface_Statistics": interface_statistics,
		"Interface_Status": interface_status, "OpenVPN_Client_Status": openvpn_client_status, "OpenVPN_Connected_Clients": openvpn_connected_clients,
		"Services_Status": services_status}