From 84991434ec17b4712b9cee9c8caa7c461fccc407 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Mon, 2 May 2022 20:20:29 +0200 Subject: [PATCH 01/23] adding port to firewall rule --- ESPFirewall/lib/Firewall/src/API.cpp | 6 ++ ESPFirewall/lib/Firewall/src/API.hpp | 13 ++-- ESPFirewall/lib/Firewall/src/Rules.cpp | 11 +++- ESPFirewall/lib/Firewall/src/Rules.hpp | 2 +- ESPFirewall/lib/Firewall/src/Utils.cpp | 82 ++++++++++++++++++++++++-- ESPFirewall/lib/Firewall/src/Utils.hpp | 26 +++++++- 6 files changed, 121 insertions(+), 19 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index aa6ab10..aae8084 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -157,6 +157,8 @@ namespace fw firewall_rule_t *rule_ptr = add_rule_to_firewall( this->server->arg("source"), this->server->arg("destination"), + this->server->arg("port_from"), + this->server->arg("port_to"), this->server->arg("protocol"), this->server->arg("target")); this->json_generic_response(this->construct_json_firewall_rule(rule_ptr), 200); @@ -188,6 +190,8 @@ namespace fw return this->server->hasArg("source") || this->server->hasArg("destination") || this->server->hasArg("protocol") || + this->server->hasArg("port_from") || + this->server->hasArg("port_to") || this->server->hasArg("target"); } } @@ -228,6 +232,8 @@ namespace fw serialized_string += json_new_attribute("key", rule_ptr->key); serialized_string += json_new_attribute("source", rule_ptr->source); serialized_string += json_new_attribute("destination", rule_ptr->destination); + serialized_string += json_new_attribute("port_from", rule_ptr->destination); + serialized_string += json_new_attribute("port_to", rule_ptr->destination); serialized_string += json_new_attribute("protocol", protocol_to_string(rule_ptr->protocol)); serialized_string += json_new_attribute("target", target_to_string(rule_ptr->target), true); serialized_string += "}"; diff --git a/ESPFirewall/lib/Firewall/src/API.hpp b/ESPFirewall/lib/Firewall/src/API.hpp index effac7d..4ef9c82 100644 --- a/ESPFirewall/lib/Firewall/src/API.hpp +++ b/ESPFirewall/lib/Firewall/src/API.hpp @@ -14,14 +14,6 @@ namespace fw { - typedef struct api_endpoints - { - char uri[40]; - char method[7]; - char description[30]; - struct api_endpoints *next; - } api_endpoint_t; - class API : public Rules { private: @@ -62,6 +54,11 @@ namespace fw uint16_t server_port; void handle_client(); String get_url_base(); + String protocol_to_string(firewall_protocol_t &protocol); + firewall_protocol_t string_to_protocol(String &protocol); + String target_to_string(firewall_target_t &target); + firewall_target_t string_to_target(String &target); + String response_code_to_string(const uint16_t response_code); public: API(const char *cert, const char *key, const char *username, const char *password, const String ip, const uint16_t port); diff --git a/ESPFirewall/lib/Firewall/src/Rules.cpp b/ESPFirewall/lib/Firewall/src/Rules.cpp index e2f804e..f009e60 100644 --- a/ESPFirewall/lib/Firewall/src/Rules.cpp +++ b/ESPFirewall/lib/Firewall/src/Rules.cpp @@ -38,14 +38,21 @@ namespace fw rule_ptr->next = NULL; } - firewall_rule_t *Rules::add_rule_to_firewall(String source, String destination, String protocol, String target) + firewall_rule_t *Rules::add_rule_to_firewall( + String source, + String destination, + String port_from, + String port_to, + String protocol, + String target) { firewall_rule_t *rule_ptr = (firewall_rule_t *)malloc(sizeof(firewall_rule_t)); rule_ptr->key = ++amount_of_rules; strncpy(rule_ptr->source, source.c_str(), sizeof(rule_ptr->source)); strncpy(rule_ptr->destination, destination.c_str(), sizeof(rule_ptr->destination)); - + rule_ptr->port_from = port_from.toInt(); + rule_ptr->port_to = port_to.toInt(); rule_ptr->protocol = string_to_protocol(protocol); rule_ptr->target = string_to_target(target); diff --git a/ESPFirewall/lib/Firewall/src/Rules.hpp b/ESPFirewall/lib/Firewall/src/Rules.hpp index 1656573..d9f1389 100644 --- a/ESPFirewall/lib/Firewall/src/Rules.hpp +++ b/ESPFirewall/lib/Firewall/src/Rules.hpp @@ -13,7 +13,7 @@ namespace fw firewall_rule_t *rule_head = NULL; void add_rule_to_firewall(firewall_rule_t *); - firewall_rule_t *add_rule_to_firewall(String source, String destination, String protocol, String target); + firewall_rule_t *add_rule_to_firewall(String, String, String, String, String, String); firewall_rule_t *get_rule_from_firewall(uint8_t); ok_t delete_rule_from_firewall(uint8_t); diff --git a/ESPFirewall/lib/Firewall/src/Utils.cpp b/ESPFirewall/lib/Firewall/src/Utils.cpp index 4eeeaac..e0f1783 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.cpp +++ b/ESPFirewall/lib/Firewall/src/Utils.cpp @@ -52,16 +52,88 @@ namespace fw { switch (response_code) { + case 100: + return F("Continue"); + case 101: + return F("Switching Protocols"); case 200: - return "success"; + return F("OK"); + case 201: + return F("Created"); + case 202: + return F("Accepted"); + case 203: + return F("Non-Authoritative Information"); + case 204: + return F("No Content"); + case 205: + return F("Reset Content"); + case 206: + return F("Partial Content"); + case 300: + return F("Multiple Choices"); + case 301: + return F("Moved Permanently"); + case 302: + return F("Found"); + case 303: + return F("See Other"); + case 304: + return F("Not Modified"); + case 305: + return F("Use Proxy"); + case 307: + return F("Temporary Redirect"); + case 400: + return F("Bad Request"); + case 401: + return F("Unauthorized"); + case 402: + return F("Payment Required"); case 403: - return "unauthorized"; + return F("Forbidden"); case 404: - return "not found"; + return F("Not Found"); + case 405: + return F("Method Not Allowed"); + case 406: + return F("Not Acceptable"); + case 407: + return F("Proxy Authentication Required"); + case 408: + return F("Request Time-out"); + case 409: + return F("Conflict"); + case 410: + return F("Gone"); + case 411: + return F("Length Required"); + case 412: + return F("Precondition Failed"); + case 413: + return F("Request Entity Too Large"); + case 414: + return F("Request-URI Too Large"); + case 415: + return F("Unsupported Media Type"); + case 416: + return F("Requested range not satisfiable"); + case 417: + return F("Expectation Failed"); case 500: - return "server error"; + return F("Internal Server Error"); + case 501: + return F("Not Implemented"); + case 502: + return F("Bad Gateway"); + case 503: + return F("Service Unavailable"); + case 504: + return F("Gateway Time-out"); + case 505: + return F("HTTP Version not supported"); default: - return "unknown error"; + return F(""); } } diff --git a/ESPFirewall/lib/Firewall/src/Utils.hpp b/ESPFirewall/lib/Firewall/src/Utils.hpp index c2e6d03..2aa156e 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.hpp +++ b/ESPFirewall/lib/Firewall/src/Utils.hpp @@ -6,9 +6,6 @@ namespace fw { - static const uint8_t IPV4ADDRESS_LENGTH = 16; - static const uint8_t CREDENTIALS_LENGTH = 32; - typedef enum firewall_targets : uint8_t { TARGET_REJECT = 0, @@ -36,22 +33,45 @@ namespace fw DENIED = 1, } auth_t; + static const uint8_t IPV4ADDRESS_LENGTH = 16; typedef struct firewall_rules { uint8_t key; char source[IPV4ADDRESS_LENGTH]; char destination[IPV4ADDRESS_LENGTH]; + uint16_t port_from; // port is max 65565 + uint16_t port_to; firewall_protocol_t protocol; firewall_target_t target; struct firewall_rules *next; } firewall_rule_t; + const byte numChars = 12; + const char firewall_fields[][numChars] = { + "key", + "source", + "destination", + "port_from", + "port_to", + "protocol", + "target", + }; + + static const uint8_t CREDENTIALS_LENGTH = 32; typedef struct credentials { char password[CREDENTIALS_LENGTH]; char username[CREDENTIALS_LENGTH]; } credential_t; + typedef struct api_endpoints + { + char uri[40]; + char method[7]; + char description[30]; + struct api_endpoints *next; + } api_endpoint_t; + String protocol_to_string(firewall_protocol_t &protocol); firewall_protocol_t string_to_protocol(String &protocol); String target_to_string(firewall_target_t &target); From 09a04b60a97b7767e08d682362a9f059876fe1f6 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Mon, 2 May 2022 20:49:05 +0200 Subject: [PATCH 02/23] increase storage --- ESPFirewall/lib/Firewall/src/Storage.cpp | 38 +++++++++++------------- ESPFirewall/lib/Firewall/src/Storage.hpp | 7 ++--- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Storage.cpp b/ESPFirewall/lib/Firewall/src/Storage.cpp index 99fea25..f4e56c2 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.cpp +++ b/ESPFirewall/lib/Firewall/src/Storage.cpp @@ -4,10 +4,7 @@ namespace fw { Storage::Storage() { -#ifdef ESP32 - if (this->mount_spiffs() == ERROR) - endless_loop(); -#elif defined(ESP8266) +#ifdef ESP8266 this->setup_eeprom(); #endif } @@ -16,23 +13,6 @@ namespace fw { } - ok_t Storage::mount_spiffs() - { -#ifdef ESP32 - if (!SPIFFS.begin(false)) - { - if (!SPIFFS.begin(true)) - { - Serial.println("SPIFFS cannot be mounted"); - return ERROR; - }; - } - return SUCCESS; -#elif defined(ESP8266) - return NO_ACTION; -#endif - } - void Storage::setup_eeprom() { #ifdef ESP8266 @@ -47,6 +27,8 @@ namespace fw uint8_t total_space_needed = 0; total_space_needed += sizeof(rule.source); total_space_needed += sizeof(rule.destination); + total_space_needed += sizeof(rule.port_from); + total_space_needed += sizeof(rule.port_to); total_space_needed += sizeof(rule.target); total_space_needed += sizeof(rule.protocol); // key-1 because key will be in range 1-255, but we need 1 less for multiplication @@ -107,6 +89,8 @@ namespace fw this->memory.begin(rulename, true); strncpy(rule_ptr->source, this->memory.getString("source", "0.0.0.0").c_str(), sizeof(rule_ptr->source)); strncpy(rule_ptr->destination, this->memory.getString("destination", "0.0.0.0").c_str(), sizeof(rule_ptr->source)); + rule_ptr->port_from = this->memory.getUChar("port_from", 0); + rule_ptr->port_to = this->memory.getUChar("port_to", 0); rule_ptr->protocol = static_cast(this->memory.getUChar("protocol", PROTOCOL_ALL)); rule_ptr->target = static_cast(this->memory.getUChar("target", TARGET_REJECT)); this->memory.end(); @@ -124,6 +108,12 @@ namespace fw strncpy(rule_ptr->destination, destination, sizeof(rule_ptr->destination)); eespom_position += sizeof(rule_ptr->destination); + rule_ptr->port_from = EEPROM.read(eespom_position); + eespom_position += sizeof(rule_ptr->port_from); + + rule_ptr->port_to = EEPROM.read(eespom_position); + eespom_position += sizeof(rule_ptr->port_to); + rule_ptr->protocol = static_cast(EEPROM.read(eespom_position)); eespom_position += sizeof(rule_ptr->protocol); @@ -153,6 +143,8 @@ namespace fw this->memory.begin(rulename, false); this->memory.putString("source", rule_ptr->source); this->memory.putString("destination", rule_ptr->destination); + this->memory.putUChar("port_from", rule_ptr->port_from); + this->memory.putUChar("port_to", rule_ptr->port_to); this->memory.putUChar("protocol", rule_ptr->protocol); this->memory.putUChar("target", rule_ptr->target); @@ -164,6 +156,10 @@ namespace fw eespom_position += sizeof(rule_ptr->source); EEPROM.put(eespom_position, rule_ptr->destination); eespom_position += sizeof(rule_ptr->destination); + EEPROM.put(eespom_position, rule_ptr->port_from); + eespom_position += sizeof(rule_ptr->port_from); + EEPROM.put(eespom_position, rule_ptr->port_to); + eespom_position += sizeof(rule_ptr->port_to); EEPROM.put(eespom_position, rule_ptr->protocol); eespom_position += sizeof(rule_ptr->protocol); EEPROM.put(eespom_position, rule_ptr->target); diff --git a/ESPFirewall/lib/Firewall/src/Storage.hpp b/ESPFirewall/lib/Firewall/src/Storage.hpp index e5996ab..d4f853a 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.hpp +++ b/ESPFirewall/lib/Firewall/src/Storage.hpp @@ -18,16 +18,15 @@ namespace fw #ifdef ESP32 Preferences memory; #elif defined(ESP8266) - // Storage per firewall rule is 34 Byte - // Space for 15 Rules is 510 Byte + // Storage per firewall rule is 42 Byte + // Space for 15 Rules is 630 Byte // plus 10 byte for settings - const uint16_t eeprom_size = 520; + const uint16_t eeprom_size = 640; const uint8_t security_number = 93; const uint16_t eeprom_settings_head = 0; const uint16_t eeprom_amout_of_rules_head = eeprom_settings_head + 1; const uint16_t eeprom_rules_head = 10; #endif - ok_t mount_spiffs(); void setup_eeprom(); uint16_t eeprom_rule_position(uint8_t); From 3cf4f4445a5848a73133ba1c7c66162f3ccdf463 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Mon, 2 May 2022 20:49:18 +0200 Subject: [PATCH 03/23] simplify --- ESPFirewall/lib/Firewall/src/API.cpp | 12 ++++++------ ESPFirewall/lib/Firewall/src/API.hpp | 5 ----- ESPFirewall/lib/Firewall/src/Utils.hpp | 9 ++++----- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index aae8084..9209823 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -187,12 +187,12 @@ namespace fw return false; else { - return this->server->hasArg("source") || - this->server->hasArg("destination") || - this->server->hasArg("protocol") || - this->server->hasArg("port_from") || - this->server->hasArg("port_to") || - this->server->hasArg("target"); + for (uint8_t i = 0; i < firewall_fields_amount; i++) + { + if (!this->server->hasArg(firewall_fields[i])) + return false; + } + return true; } } diff --git a/ESPFirewall/lib/Firewall/src/API.hpp b/ESPFirewall/lib/Firewall/src/API.hpp index 4ef9c82..e60404e 100644 --- a/ESPFirewall/lib/Firewall/src/API.hpp +++ b/ESPFirewall/lib/Firewall/src/API.hpp @@ -54,11 +54,6 @@ namespace fw uint16_t server_port; void handle_client(); String get_url_base(); - String protocol_to_string(firewall_protocol_t &protocol); - firewall_protocol_t string_to_protocol(String &protocol); - String target_to_string(firewall_target_t &target); - firewall_target_t string_to_target(String &target); - String response_code_to_string(const uint16_t response_code); public: API(const char *cert, const char *key, const char *username, const char *password, const String ip, const uint16_t port); diff --git a/ESPFirewall/lib/Firewall/src/Utils.hpp b/ESPFirewall/lib/Firewall/src/Utils.hpp index 2aa156e..ec19025 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.hpp +++ b/ESPFirewall/lib/Firewall/src/Utils.hpp @@ -39,16 +39,15 @@ namespace fw uint8_t key; char source[IPV4ADDRESS_LENGTH]; char destination[IPV4ADDRESS_LENGTH]; - uint16_t port_from; // port is max 65565 - uint16_t port_to; + uint32_t port_from; // port can be max 65565 + uint32_t port_to; // range of uint16_t: 0 to 65535 firewall_protocol_t protocol; firewall_target_t target; struct firewall_rules *next; } firewall_rule_t; - const byte numChars = 12; - const char firewall_fields[][numChars] = { - "key", + static const uint8_t firewall_fields_amount = 6; + const char firewall_fields[firewall_fields_amount][12] = { "source", "destination", "port_from", From 3e1ec7ebb081fe4854aa4901894ddb8975c0c33e Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Mon, 2 May 2022 20:53:29 +0200 Subject: [PATCH 04/23] ports added --- ESPFirewall/lib/Firewall/src/API.cpp | 6 +++--- ESPFirewall/lib/Firewall/src/API.hpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index 9209823..f049967 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -205,7 +205,7 @@ namespace fw return json_string; } - String API::json_new_attribute(String key, uint8_t value, bool last) + String API::json_new_attribute(String key, uint32_t value, bool last) { return json_new_attribute(key, String(value), last); } @@ -232,8 +232,8 @@ namespace fw serialized_string += json_new_attribute("key", rule_ptr->key); serialized_string += json_new_attribute("source", rule_ptr->source); serialized_string += json_new_attribute("destination", rule_ptr->destination); - serialized_string += json_new_attribute("port_from", rule_ptr->destination); - serialized_string += json_new_attribute("port_to", rule_ptr->destination); + serialized_string += json_new_attribute("port_from", rule_ptr->port_from); + serialized_string += json_new_attribute("port_to", rule_ptr->port_to); serialized_string += json_new_attribute("protocol", protocol_to_string(rule_ptr->protocol)); serialized_string += json_new_attribute("target", target_to_string(rule_ptr->target), true); serialized_string += "}"; diff --git a/ESPFirewall/lib/Firewall/src/API.hpp b/ESPFirewall/lib/Firewall/src/API.hpp index e60404e..f7377ff 100644 --- a/ESPFirewall/lib/Firewall/src/API.hpp +++ b/ESPFirewall/lib/Firewall/src/API.hpp @@ -40,7 +40,7 @@ namespace fw bool request_has_firewall_parameter(); String json_new_attribute(String key, String value, bool last = false); - String json_new_attribute(String key, uint8_t value, bool last = false); + String json_new_attribute(String key, uint32_t value, bool last = false); void json_generic_response(String serialized_string, const uint16_t response_code); void json_message_response(String message, const uint16_t response_code); String construct_json_firewall_rule(firewall_rule_t *); From 50ebe9a5a43a8ee982e4dbbfd46533dcc102ee0f Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Mon, 2 May 2022 21:01:08 +0200 Subject: [PATCH 05/23] thinking about how to compare firewall rules --- ESPFirewall/lib/Firewall/src/Firewall.hpp | 8 ++++++++ ESPFirewall/src/main.cpp | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/ESPFirewall/lib/Firewall/src/Firewall.hpp b/ESPFirewall/lib/Firewall/src/Firewall.hpp index bbd3b8f..e0dcaee 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.hpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.hpp @@ -12,6 +12,7 @@ namespace fw Firewall(const char *, const char *, const char *, const char *, const String ip, const uint16_t = 8080); ~Firewall(); void handle_api_client(); + bool check_client(WiFiClient); }; Firewall::Firewall(const char *cert, const char *key, const char *username, const char *password, const String ip, const uint16_t port) @@ -21,6 +22,13 @@ namespace fw { handle_client(); } + bool Firewall::check_client(WiFiClient client) + { + if (client.remoteIP()) + return false; + else + return true; + } } #endif diff --git a/ESPFirewall/src/main.cpp b/ESPFirewall/src/main.cpp index 0d0d349..c0aa9ac 100644 --- a/ESPFirewall/src/main.cpp +++ b/ESPFirewall/src/main.cpp @@ -11,6 +11,7 @@ fw::Firewall *firewall; String ip = "0.0.0.0"; +WiFiServer wifiServer(80); void setup_wifi() { @@ -27,6 +28,7 @@ void setup_wifi() Serial.print("IP Address: "); ip = WiFi.localIP().toString(); Serial.println(ip); + wifiServer.begin(); } void setup() @@ -37,5 +39,19 @@ void setup() void loop() { + WiFiClient client = wifiServer.available(); + if (client) + { + Serial.print("Client connected with IP:"); + Serial.println(client.remoteIP()); + + if (firewall->check_client(client)) + Serial.println("good client"); + else + Serial.println("bad client"); + + client.stop(); + Serial.println("Client disconnected"); + } firewall->handle_api_client(); } \ No newline at end of file From 0768877ea86feb16eb18986a1e1dd48d52bbc56d Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Mon, 2 May 2022 21:02:01 +0200 Subject: [PATCH 06/23] python test client --- ESPFirewall/app.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 ESPFirewall/app.py diff --git a/ESPFirewall/app.py b/ESPFirewall/app.py new file mode 100644 index 0000000..63d0cf1 --- /dev/null +++ b/ESPFirewall/app.py @@ -0,0 +1,11 @@ +import socket + +sock = socket.socket() + +host = "10.93.0.246" +port = 80 + +sock.connect((host, port)) +sock.send("test".encode()) +sock.close() + From e25cca86f19b0c21b41448a43b47c8c0586f11c1 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:09:04 +0200 Subject: [PATCH 07/23] cleanup storage --- ESPFirewall/lib/Firewall/src/Storage.hpp | 25 +++++++++++------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Storage.hpp b/ESPFirewall/lib/Firewall/src/Storage.hpp index d4f853a..1f44da4 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.hpp +++ b/ESPFirewall/lib/Firewall/src/Storage.hpp @@ -3,7 +3,6 @@ #ifdef ESP32 #include "Preferences.h" -#include "SPIFFS.h" #elif defined(ESP8266) #include "EEPROM.h" #endif @@ -14,13 +13,16 @@ namespace fw { class Storage { + public: + Storage(); + ~Storage(); + private: #ifdef ESP32 Preferences memory; #elif defined(ESP8266) // Storage per firewall rule is 42 Byte - // Space for 15 Rules is 630 Byte - // plus 10 byte for settings + // Space for 15 Rules is 630 Byte plus 10 byte for settings const uint16_t eeprom_size = 640; const uint8_t security_number = 93; const uint16_t eeprom_settings_head = 0; @@ -28,19 +30,14 @@ namespace fw const uint16_t eeprom_rules_head = 10; #endif void setup_eeprom(); - uint16_t eeprom_rule_position(uint8_t); + uint16_t eeprom_rule_position(uint8_t key); protected: - uint8_t retrieve_settings_value(const char *); - void store_settings_value(const char *, const uint8_t); - - firewall_rule_t *retrieve_firewall_rule(const uint8_t); - void store_all_firewall_rules(firewall_rule_t *); - void store_firewall_rule(firewall_rule_t *); - - public: - Storage(); - ~Storage(); + uint8_t retrieve_settings_value(const char *key); + void store_settings_value(const char *key, const uint8_t new_amount); + firewall_rule_t *retrieve_firewall_rule(const uint8_t key); + void store_all_firewall_rules(firewall_rule_t *rule_head); + void store_firewall_rule(firewall_rule_t *rule_ptr); }; } From 1e87f21334b0b97ff63863ffe057eae0e0816e5c Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:15:01 +0200 Subject: [PATCH 08/23] cleanup Firewall --- ESPFirewall/lib/Firewall/src/Firewall.cpp | 121 ++++++++++++++++++++++ ESPFirewall/lib/Firewall/src/Firewall.hpp | 39 +++---- 2 files changed, 137 insertions(+), 23 deletions(-) create mode 100644 ESPFirewall/lib/Firewall/src/Firewall.cpp diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp new file mode 100644 index 0000000..72f178b --- /dev/null +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -0,0 +1,121 @@ +#include "Firewall.hpp" + +namespace fw +{ + Firewall::Firewall() + { + this->amount_of_rules = retrieve_settings_value("amount_of_rules"); + for (uint8_t i = 1; i <= this->amount_of_rules; i++) + { + firewall_rule_t *rule_ptr = retrieve_firewall_rule(i); + this->add_rule_to_firewall(rule_ptr, false); + } + } + + Firewall::~Firewall() + { + } + + firewall_rule_t *Firewall::get_rule_head() + { + return this->rule_head; + } + + void Firewall::add_rule_to_firewall(firewall_rule_t *rule_ptr, const bool save_in_eeprom) + { + store_settings_value("amount_of_rules", this->amount_of_rules); + if (save_in_eeprom) + Storage::store_firewall_rule(rule_ptr); + if (this->rule_head == NULL) + { + this->rule_head = rule_ptr; + rule_ptr->next = NULL; + return; + } + firewall_rule_t *current_rule; + current_rule = this->rule_head; + while (current_rule->next != NULL) + { + current_rule = current_rule->next; + } + current_rule->next = rule_ptr; + rule_ptr->next = NULL; + } + + firewall_rule_t *Firewall::add_rule_to_firewall(String source, String destination, String port_from, String port_to, String protocol, String target) + { + firewall_rule_t *rule_ptr = (firewall_rule_t *)malloc(sizeof(firewall_rule_t)); + rule_ptr->key = ++this->amount_of_rules; + + strncpy(rule_ptr->source, source.c_str(), sizeof(rule_ptr->source)); + strncpy(rule_ptr->destination, destination.c_str(), sizeof(rule_ptr->destination)); + rule_ptr->port_from = port_from.toInt(); + rule_ptr->port_to = port_to.toInt(); + rule_ptr->protocol = string_to_protocol(protocol); + rule_ptr->target = string_to_target(target); + + add_rule_to_firewall(rule_ptr); + return rule_ptr; + } + + firewall_rule_t *Firewall::get_rule_from_firewall(const uint8_t key) + { + firewall_rule_t *rule_ptr = this->rule_head; + if (this->rule_head == NULL) + { + return NULL; + } + while (rule_ptr->key != key) + { + if (rule_ptr->next == NULL) + { + return NULL; + } + else + { + rule_ptr = rule_ptr->next; + } + } + return rule_ptr; + } + + ok_t Firewall::delete_rule_from_firewall(const uint8_t key) + { + if (this->rule_head == NULL) + return NO_ACTION; + firewall_rule_t *current_rule = this->rule_head; + firewall_rule_t *previous_rule = NULL; + firewall_rule_t *temp = NULL; + while (current_rule->key != key) + { + if (current_rule->next == NULL) + return NO_ACTION; + else + { + previous_rule = current_rule; + current_rule = current_rule->next; + } + } + if (current_rule == this->rule_head) + { + this->rule_head = rule_head->next; + temp = this->rule_head; + } + else + { + previous_rule->next = current_rule->next; + temp = previous_rule->next; + } + while (temp != NULL) + { + temp->key--; + temp = temp->next; + } + free(current_rule); + this->amount_of_rules--; + Storage::store_settings_value("amount_of_rules", this->amount_of_rules); + if (this->amount_of_rules != 0) + Storage::store_all_firewall_rules(rule_head); + return SUCCESS; + } +} diff --git a/ESPFirewall/lib/Firewall/src/Firewall.hpp b/ESPFirewall/lib/Firewall/src/Firewall.hpp index e0dcaee..c033dbe 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.hpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.hpp @@ -1,34 +1,27 @@ -#ifndef FIREWALL_HPP -#define FIREWALL_HPP +#ifndef ESP32_FIREWALL_HPP +#define ESP32_FIREWALL_HPP -#include "API.hpp" +#include "Utils.hpp" +#include "Storage.hpp" namespace fw { - class Firewall : public API + class Firewall : public Storage { - private: public: - Firewall(const char *, const char *, const char *, const char *, const String ip, const uint16_t = 8080); + Firewall(); ~Firewall(); - void handle_api_client(); - bool check_client(WiFiClient); - }; - Firewall::Firewall(const char *cert, const char *key, const char *username, const char *password, const String ip, const uint16_t port) - : API(cert, key, username, password, ip, port) {} - Firewall::~Firewall() {} - void Firewall::handle_api_client() - { - handle_client(); - } - bool Firewall::check_client(WiFiClient client) - { - if (client.remoteIP()) - return false; - else - return true; - } + firewall_rule_t *get_rule_head(); + void add_rule_to_firewall(firewall_rule_t *rule_ptr, const bool save_in_eeprom = true); + firewall_rule_t *add_rule_to_firewall(String source, String destination, String port_from, String port_to, String protocol, String target); + firewall_rule_t *get_rule_from_firewall(const uint8_t key); + ok_t delete_rule_from_firewall(const uint8_t key); + + protected: + uint8_t amount_of_rules = 0; + firewall_rule_t *rule_head = NULL; + }; } #endif From 3e664dd408723240b0748c40b37ee4164d598427 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:15:10 +0200 Subject: [PATCH 09/23] remove rules class --- ESPFirewall/lib/Firewall/src/Rules.cpp | 123 ------------------------- ESPFirewall/lib/Firewall/src/Rules.hpp | 26 ------ 2 files changed, 149 deletions(-) delete mode 100644 ESPFirewall/lib/Firewall/src/Rules.cpp delete mode 100644 ESPFirewall/lib/Firewall/src/Rules.hpp diff --git a/ESPFirewall/lib/Firewall/src/Rules.cpp b/ESPFirewall/lib/Firewall/src/Rules.cpp deleted file mode 100644 index f009e60..0000000 --- a/ESPFirewall/lib/Firewall/src/Rules.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "Rules.hpp" - -namespace fw -{ - Rules::Rules() - { - this->amount_of_rules = retrieve_settings_value("amount_of_rules"); - Serial.print("Available Firewall Rules: "); - Serial.println(amount_of_rules); - for (uint8_t i = 1; i <= this->amount_of_rules; i++) - { - firewall_rule_t *rule_ptr = retrieve_firewall_rule(i); - add_rule_to_firewall(rule_ptr); - } - } - - Rules::~Rules() - { - } - - void Rules::add_rule_to_firewall(firewall_rule_t *rule_ptr) - { - store_settings_value("amount_of_rules", this->amount_of_rules); - store_firewall_rule(rule_ptr); - firewall_rule_t *temp; - if (this->rule_head == NULL) - { - this->rule_head = rule_ptr; - rule_ptr->next = NULL; - return; - } - temp = this->rule_head; - while (temp->next != NULL) - { - temp = temp->next; - } - temp->next = rule_ptr; - rule_ptr->next = NULL; - } - - firewall_rule_t *Rules::add_rule_to_firewall( - String source, - String destination, - String port_from, - String port_to, - String protocol, - String target) - { - firewall_rule_t *rule_ptr = (firewall_rule_t *)malloc(sizeof(firewall_rule_t)); - rule_ptr->key = ++amount_of_rules; - - strncpy(rule_ptr->source, source.c_str(), sizeof(rule_ptr->source)); - strncpy(rule_ptr->destination, destination.c_str(), sizeof(rule_ptr->destination)); - rule_ptr->port_from = port_from.toInt(); - rule_ptr->port_to = port_to.toInt(); - rule_ptr->protocol = string_to_protocol(protocol); - rule_ptr->target = string_to_target(target); - - add_rule_to_firewall(rule_ptr); - return rule_ptr; - } - - firewall_rule_t *Rules::get_rule_from_firewall(uint8_t key) - { - firewall_rule_t *rule_ptr = this->rule_head; - if (this->rule_head == NULL) - { - return NULL; - } - while (rule_ptr->key != key) - { - if (rule_ptr->next == NULL) - { - return NULL; - } - else - { - rule_ptr = rule_ptr->next; - } - } - return rule_ptr; - } - - ok_t Rules::delete_rule_from_firewall(uint8_t key) - { - if (this->rule_head == NULL) - return NO_ACTION; - firewall_rule_t *current_rule_ptr = this->rule_head; - firewall_rule_t *previous_rule_ptr = NULL; - firewall_rule_t *temp = NULL; - while (current_rule_ptr->key != key) - { - if (current_rule_ptr->next == NULL) - return NO_ACTION; - else - { - previous_rule_ptr = current_rule_ptr; - current_rule_ptr = current_rule_ptr->next; - } - } - if (current_rule_ptr == this->rule_head) - { - this->rule_head = rule_head->next; - temp = this->rule_head; - } - else - { - previous_rule_ptr->next = current_rule_ptr->next; - temp = previous_rule_ptr->next; - } - while (temp != NULL) - { - temp->key--; - temp = temp->next; - } - free(current_rule_ptr); - this->amount_of_rules--; - store_settings_value("amount_of_rules", this->amount_of_rules); - if (this->amount_of_rules != 0) - store_all_firewall_rules(rule_head); - return SUCCESS; - } -} diff --git a/ESPFirewall/lib/Firewall/src/Rules.hpp b/ESPFirewall/lib/Firewall/src/Rules.hpp deleted file mode 100644 index d9f1389..0000000 --- a/ESPFirewall/lib/Firewall/src/Rules.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ESP32_FIREWALL_HPP -#define ESP32_FIREWALL_HPP - -#include "Utils.hpp" -#include "Storage.hpp" - -namespace fw -{ - class Rules : public Storage - { - protected: - uint8_t amount_of_rules = 0; - firewall_rule_t *rule_head = NULL; - - void add_rule_to_firewall(firewall_rule_t *); - firewall_rule_t *add_rule_to_firewall(String, String, String, String, String, String); - firewall_rule_t *get_rule_from_firewall(uint8_t); - ok_t delete_rule_from_firewall(uint8_t); - - public: - Rules(); - ~Rules(); - }; -} - -#endif From d08a0599a66664515799dbbac0ae38b81db2174e Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:22:51 +0200 Subject: [PATCH 10/23] cleanup API --- ESPFirewall/lib/Firewall/src/API.cpp | 42 +++++++++++++--------------- ESPFirewall/lib/Firewall/src/API.hpp | 37 ++++++++++++------------ 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index f049967..75b9dcd 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -2,10 +2,11 @@ namespace fw { - API::API(const char *cert, const char *key, const char *username, const char *password, const String ip, const uint16_t port) + API::API(fw::Firewall *firewall, const char *cert, const char *key, const char *username, const char *password, const uint16_t port) { - this->server_ip = ip; - this->server_port = port; + this->firewall = firewall; + this->api_ip = WiFi.localIP().toString(); + this->api_port = port; if (this->setup_auth(username, password) == ERROR) endless_loop(); #ifdef ESP32 @@ -32,9 +33,9 @@ namespace fw String API::get_url_base() { #ifdef ESP32 - return "http://" + this->server_ip + ":" + this->server_port; + return "http://" + this->api_ip + ":" + this->api_port; #elif defined(ESP8266) - return "https://" + this->server_ip + ":" + this->server_port; + return "https://" + this->api_ip + ":" + this->api_port; #endif } @@ -75,22 +76,19 @@ namespace fw this->server->getServer().setCache(serverCache); #endif this->server->on("/firewall", HTTP_GET, std::bind(&API::get_firewall_rules_handler, this)); - add_api_endpoint("/firewall", "GET", "Get all Firewall Rules"); - this->server->on(UriRegex("/firewall/([0-9]+)"), HTTP_GET, std::bind(&API::get_firewall_rule_handler, this)); - add_api_endpoint("/firewall/1", "GET", "Get Firewall Rule by key"); - this->server->on("/firewall", HTTP_POST, std::bind(&API::post_firewall_handler, this)); - add_api_endpoint("/firewall", "POST", "Create Firewall Rule"); - this->server->on(UriRegex("/firewall/([0-9]+)"), HTTP_DELETE, std::bind(&API::delete_firewall_handler, this)); - add_api_endpoint("/firewall/1", "DELETE", "Delete Firewall Rule by key"); - - this->server->on("/api", HTTP_GET, std::bind(&API::api_endpoints_handler, this)); + this->server->on("/api", HTTP_GET, std::bind(&API::get_endpoint_list_handler, this)); this->server->onNotFound(std::bind(&API::not_found_handler, this)); + + add_endpoint_to_list("/firewall", "GET", "Get all Firewall Rules"); + add_endpoint_to_list("/firewall/1", "GET", "Get Firewall Rule by key"); + add_endpoint_to_list("/firewall", "POST", "Create Firewall Rule"); + add_endpoint_to_list("/firewall/1", "DELETE", "Delete Firewall Rule by key"); } - void API::add_api_endpoint(const String uri, const char *method, const char *description) + void API::add_endpoint_to_list(const String uri, const char *method, const char *description) { api_endpoint_t *temp; const String url = get_url_base() + uri; @@ -123,7 +121,7 @@ namespace fw 404); } - void API::api_endpoints_handler() + void API::get_endpoint_list_handler() { this->json_generic_response(this->construct_json_api(), 200); } @@ -134,7 +132,7 @@ namespace fw return; String param = this->server->pathArg(0); int rule_number = atoi(param.c_str()); - firewall_rule_t *rule_ptr = get_rule_from_firewall(rule_number); + firewall_rule_t *rule_ptr = firewall->get_rule_from_firewall(rule_number); if (rule_ptr == NULL) this->json_message_response("rule does not exist", 404); else @@ -152,9 +150,9 @@ namespace fw { if (this->check_auth() == DENIED) return; - if (request_has_firewall_parameter()) + if (request_has_all_firewall_parameter()) { - firewall_rule_t *rule_ptr = add_rule_to_firewall( + firewall_rule_t *rule_ptr = firewall->add_rule_to_firewall( this->server->arg("source"), this->server->arg("destination"), this->server->arg("port_from"), @@ -175,13 +173,13 @@ namespace fw return; String param = this->server->pathArg(0); int rule_number = atoi(param.c_str()); - if (delete_rule_from_firewall(rule_number) == SUCCESS) + if (firewall->delete_rule_from_firewall(rule_number) == SUCCESS) this->json_message_response("firewall rule deleted", 200); else this->json_message_response("cannot delete firewall rule", 500); } - bool API::request_has_firewall_parameter() + bool API::request_has_all_firewall_parameter() { if (!this->server->args()) return false; @@ -242,7 +240,7 @@ namespace fw String API::construct_json_firewall() { - firewall_rule_t *rule_ptr = rule_head; + firewall_rule_t *rule_ptr = firewall->get_rule_head(); String serialized_string; while (rule_ptr != NULL) { diff --git a/ESPFirewall/lib/Firewall/src/API.hpp b/ESPFirewall/lib/Firewall/src/API.hpp index f7377ff..d3339da 100644 --- a/ESPFirewall/lib/Firewall/src/API.hpp +++ b/ESPFirewall/lib/Firewall/src/API.hpp @@ -8,14 +8,18 @@ #endif #include "uri/UriRegex.h" - -#include "Rules.hpp" +#include "Firewall.hpp" #include "Utils.hpp" namespace fw { - class API : public Rules + class API { + public: + API(Firewall *, const char *cert, const char *key, const char *username, const char *password, const uint16_t port = 8080); + ~API(); + void handle_client(); + private: #ifdef ESP32 WebServer *server; @@ -23,41 +27,36 @@ namespace fw BearSSL::ESP8266WebServerSecure *server; BearSSL::ServerSessions *serverCache; #endif + Firewall *firewall; credential_t credentials; api_endpoint_t *endpoint_head = NULL; + String api_ip = "0.0.0.0"; + uint16_t api_port; + String get_url_base(); ok_t setup_auth(const char *username, const char *password); auth_t check_auth(); void setup_routing(const char *cert, const char *key); - void add_api_endpoint(const String uri, const char *method, const char *description); + void add_endpoint_to_list(const String uri, const char *method, const char *description); + void not_found_handler(); + void get_endpoint_list_handler(); void get_firewall_rule_handler(); void get_firewall_rules_handler(); void post_firewall_handler(); void delete_firewall_handler(); - void not_found_handler(); - void api_endpoints_handler(); - bool request_has_firewall_parameter(); + bool request_has_all_firewall_parameter(); String json_new_attribute(String key, String value, bool last = false); String json_new_attribute(String key, uint32_t value, bool last = false); void json_generic_response(String serialized_string, const uint16_t response_code); void json_message_response(String message, const uint16_t response_code); - String construct_json_firewall_rule(firewall_rule_t *); + + String construct_json_firewall_rule(firewall_rule_t *rule_ptr); String construct_json_firewall(); - String construct_json_api_endpoint(api_endpoint_t *); + String construct_json_api_endpoint(api_endpoint_t *api_ptr); String construct_json_api(); String construct_json_begin(const uint16_t response_code); - - protected: - String server_ip; - uint16_t server_port; - void handle_client(); - String get_url_base(); - - public: - API(const char *cert, const char *key, const char *username, const char *password, const String ip, const uint16_t port); - ~API(); }; } From 458e3fbc6fd73abfd76540337bfc3b1482f07677 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:28:17 +0200 Subject: [PATCH 11/23] cleanup main --- ESPFirewall/src/main.cpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/ESPFirewall/src/main.cpp b/ESPFirewall/src/main.cpp index c0aa9ac..04b8c05 100644 --- a/ESPFirewall/src/main.cpp +++ b/ESPFirewall/src/main.cpp @@ -8,9 +8,11 @@ #endif #include "Firewall.hpp" +#include "API.hpp" fw::Firewall *firewall; -String ip = "0.0.0.0"; +fw::API *firewallApi; + WiFiServer wifiServer(80); void setup_wifi() @@ -26,32 +28,18 @@ void setup_wifi() } Serial.println(); Serial.print("IP Address: "); - ip = WiFi.localIP().toString(); - Serial.println(ip); + Serial.println(WiFi.localIP()); wifiServer.begin(); } void setup() { setup_wifi(); - firewall = new fw::Firewall(cert, key, username, password, ip, 8080); + firewall = new fw::Firewall(); + firewallApi = new fw::API(firewall, cert, key, username, password); } void loop() { - WiFiClient client = wifiServer.available(); - if (client) - { - Serial.print("Client connected with IP:"); - Serial.println(client.remoteIP()); - - if (firewall->check_client(client)) - Serial.println("good client"); - else - Serial.println("bad client"); - - client.stop(); - Serial.println("Client disconnected"); - } - firewall->handle_api_client(); + firewallApi->handle_client(); } \ No newline at end of file From dfb92d6bf92b8cc1fba7232c73d05e2d56bc0d0f Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:32:40 +0200 Subject: [PATCH 12/23] run a webserver for firewall check --- ESPFirewall/src/main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ESPFirewall/src/main.cpp b/ESPFirewall/src/main.cpp index 04b8c05..43d6267 100644 --- a/ESPFirewall/src/main.cpp +++ b/ESPFirewall/src/main.cpp @@ -42,4 +42,12 @@ void setup() void loop() { firewallApi->handle_client(); + WiFiClient client = wifiServer.available(); + if (client) + { + Serial.print("Client connected with IP:"); + Serial.println(client.remoteIP()); + client.stop(); + Serial.println("Client disconnected"); + } } \ No newline at end of file From 8e29479aea6c3f10d230baba14398de8d4b94827 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 20:40:42 +0200 Subject: [PATCH 13/23] basic function to check client --- ESPFirewall/lib/Firewall/src/Firewall.cpp | 12 ++++++++++++ ESPFirewall/lib/Firewall/src/Firewall.hpp | 3 +++ ESPFirewall/src/main.cpp | 7 ++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp index 72f178b..3d13968 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.cpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -118,4 +118,16 @@ namespace fw Storage::store_all_firewall_rules(rule_head); return SUCCESS; } + + bool Firewall::is_client_allowed(WiFiClient client) + { + const char *ip = client.remoteIP().toString().c_str(); + const uint16_t port = client.remotePort(); + + Serial.print("Client connected: "); + Serial.print(client.remoteIP()); + Serial.print(":"); + Serial.println(client.remotePort()); + return true; + } } diff --git a/ESPFirewall/lib/Firewall/src/Firewall.hpp b/ESPFirewall/lib/Firewall/src/Firewall.hpp index c033dbe..2427838 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.hpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.hpp @@ -3,6 +3,7 @@ #include "Utils.hpp" #include "Storage.hpp" +#include "WiFiClient.h" namespace fw { @@ -18,6 +19,8 @@ namespace fw firewall_rule_t *get_rule_from_firewall(const uint8_t key); ok_t delete_rule_from_firewall(const uint8_t key); + bool is_client_allowed(WiFiClient client); + protected: uint8_t amount_of_rules = 0; firewall_rule_t *rule_head = NULL; diff --git a/ESPFirewall/src/main.cpp b/ESPFirewall/src/main.cpp index 43d6267..2e5e9c3 100644 --- a/ESPFirewall/src/main.cpp +++ b/ESPFirewall/src/main.cpp @@ -45,9 +45,10 @@ void loop() WiFiClient client = wifiServer.available(); if (client) { - Serial.print("Client connected with IP:"); - Serial.println(client.remoteIP()); + if (firewall->is_client_allowed(client)) + Serial.println("allowed"); + else + Serial.println("rejected"); client.stop(); - Serial.println("Client disconnected"); } } \ No newline at end of file From edacebb3a6830c40bfbc879c10f91361d9b43072 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 3 May 2022 21:00:56 +0200 Subject: [PATCH 14/23] real basic check --- ESPFirewall/lib/Firewall/src/Firewall.cpp | 24 ++++++++++++++--------- ESPFirewall/lib/Firewall/src/Firewall.hpp | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp index 3d13968..b8c0536 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.cpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -35,9 +35,7 @@ namespace fw firewall_rule_t *current_rule; current_rule = this->rule_head; while (current_rule->next != NULL) - { current_rule = current_rule->next; - } current_rule->next = rule_ptr; rule_ptr->next = NULL; } @@ -62,19 +60,13 @@ namespace fw { firewall_rule_t *rule_ptr = this->rule_head; if (this->rule_head == NULL) - { return NULL; - } while (rule_ptr->key != key) { if (rule_ptr->next == NULL) - { return NULL; - } else - { rule_ptr = rule_ptr->next; - } } return rule_ptr; } @@ -119,12 +111,26 @@ namespace fw return SUCCESS; } + bool Firewall::is_included_in_firewall(const char *ip, const uint16_t port) + { + firewall_rule_t *rule_ptr = this->rule_head; + while (rule_ptr != NULL) + { + if (strncmp(ip, rule_ptr->source, IPV4ADDRESS_LENGTH) == 0) + { + if (rule_ptr->port_from <= port && port <= rule_ptr->port_to) + return true; + } + rule_ptr = rule_ptr->next; + } + return false; + } + bool Firewall::is_client_allowed(WiFiClient client) { const char *ip = client.remoteIP().toString().c_str(); const uint16_t port = client.remotePort(); - Serial.print("Client connected: "); Serial.print(client.remoteIP()); Serial.print(":"); Serial.println(client.remotePort()); diff --git a/ESPFirewall/lib/Firewall/src/Firewall.hpp b/ESPFirewall/lib/Firewall/src/Firewall.hpp index 2427838..59976f6 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.hpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.hpp @@ -19,6 +19,7 @@ namespace fw firewall_rule_t *get_rule_from_firewall(const uint8_t key); ok_t delete_rule_from_firewall(const uint8_t key); + bool is_included_in_firewall(const char *ip, const uint16_t port); bool is_client_allowed(WiFiClient client); protected: From 1f2cb6e021d3d517c34da4cdf1d2c957acea378d Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Wed, 4 May 2022 09:13:40 +0200 Subject: [PATCH 15/23] return if ip and port are not included in firewall --- ESPFirewall/lib/Firewall/src/Firewall.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp index b8c0536..5925cbe 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.cpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -134,6 +134,6 @@ namespace fw Serial.print(client.remoteIP()); Serial.print(":"); Serial.println(client.remotePort()); - return true; + return !is_included_in_firewall(ip, port); } } From 265e0562f8572ad889ab21706e7a6b1961a3d994 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Wed, 4 May 2022 18:24:22 +0200 Subject: [PATCH 16/23] simplify --- ESPFirewall/lib/Firewall/src/API.cpp | 40 +++++++++++------------ ESPFirewall/lib/Firewall/src/Firewall.cpp | 15 ++++----- ESPFirewall/lib/Firewall/src/Firewall.hpp | 2 +- ESPFirewall/lib/Firewall/src/Storage.cpp | 40 +++++++++-------------- ESPFirewall/lib/Firewall/src/Utils.hpp | 20 ++++++++---- 5 files changed, 55 insertions(+), 62 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index 75b9dcd..e01a6ed 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -75,17 +75,17 @@ namespace fw this->server->getServer().setRSACert(new BearSSL::X509List(cert), new BearSSL::PrivateKey(key)); this->server->getServer().setCache(serverCache); #endif - this->server->on("/firewall", HTTP_GET, std::bind(&API::get_firewall_rules_handler, this)); - this->server->on(UriRegex("/firewall/([0-9]+)"), HTTP_GET, std::bind(&API::get_firewall_rule_handler, this)); - this->server->on("/firewall", HTTP_POST, std::bind(&API::post_firewall_handler, this)); - this->server->on(UriRegex("/firewall/([0-9]+)"), HTTP_DELETE, std::bind(&API::delete_firewall_handler, this)); + this->server->on("/api/firewall/rules", HTTP_GET, std::bind(&API::get_firewall_rules_handler, this)); + this->server->on(UriRegex("/api/firewall/rules/([0-9]+)"), HTTP_GET, std::bind(&API::get_firewall_rule_handler, this)); + this->server->on("/api/firewall/rules", HTTP_POST, std::bind(&API::post_firewall_handler, this)); + this->server->on(UriRegex("/api/firewall/rules/([0-9]+)"), HTTP_DELETE, std::bind(&API::delete_firewall_handler, this)); this->server->on("/api", HTTP_GET, std::bind(&API::get_endpoint_list_handler, this)); this->server->onNotFound(std::bind(&API::not_found_handler, this)); - add_endpoint_to_list("/firewall", "GET", "Get all Firewall Rules"); - add_endpoint_to_list("/firewall/1", "GET", "Get Firewall Rule by key"); - add_endpoint_to_list("/firewall", "POST", "Create Firewall Rule"); - add_endpoint_to_list("/firewall/1", "DELETE", "Delete Firewall Rule by key"); + add_endpoint_to_list("/api/firewall/rules", "GET", "Get all Firewall Rules"); + add_endpoint_to_list("/api/firewall/rules/", "GET", "Get Firewall Rule by key"); + add_endpoint_to_list("/api/firewall/rules", "POST", "Create Firewall Rule"); + add_endpoint_to_list("/api/firewall/rules/", "DELETE", "Delete Firewall Rule by key"); } void API::add_endpoint_to_list(const String uri, const char *method, const char *description) @@ -152,13 +152,12 @@ namespace fw return; if (request_has_all_firewall_parameter()) { - firewall_rule_t *rule_ptr = firewall->add_rule_to_firewall( - this->server->arg("source"), - this->server->arg("destination"), - this->server->arg("port_from"), - this->server->arg("port_to"), - this->server->arg("protocol"), - this->server->arg("target")); + String args[IPV4ADDRESS_LENGTH] = {}; + for (uint8_t i = 0; i < firewall_fields_amount; i++) + { + args[i] = this->server->arg(firewall_fields[i]); + } + firewall_rule_t *rule_ptr = firewall->add_rule_to_firewall(args); this->json_generic_response(this->construct_json_firewall_rule(rule_ptr), 200); } else @@ -228,12 +227,11 @@ namespace fw { String serialized_string = "{"; serialized_string += json_new_attribute("key", rule_ptr->key); - serialized_string += json_new_attribute("source", rule_ptr->source); - serialized_string += json_new_attribute("destination", rule_ptr->destination); - serialized_string += json_new_attribute("port_from", rule_ptr->port_from); - serialized_string += json_new_attribute("port_to", rule_ptr->port_to); - serialized_string += json_new_attribute("protocol", protocol_to_string(rule_ptr->protocol)); - serialized_string += json_new_attribute("target", target_to_string(rule_ptr->target), true); + serialized_string += json_new_attribute(firewall_fields[IP], rule_ptr->ip); + serialized_string += json_new_attribute(firewall_fields[PORT_FROM], rule_ptr->port_from); + serialized_string += json_new_attribute(firewall_fields[PORT_TO], rule_ptr->port_to); + serialized_string += json_new_attribute(firewall_fields[PROTOCOL], protocol_to_string(rule_ptr->protocol)); + serialized_string += json_new_attribute(firewall_fields[TARGET], target_to_string(rule_ptr->target), true); serialized_string += "}"; return serialized_string; } diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp index 5925cbe..7bcb501 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.cpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -40,17 +40,16 @@ namespace fw rule_ptr->next = NULL; } - firewall_rule_t *Firewall::add_rule_to_firewall(String source, String destination, String port_from, String port_to, String protocol, String target) + firewall_rule_t *Firewall::add_rule_to_firewall(String *args) { firewall_rule_t *rule_ptr = (firewall_rule_t *)malloc(sizeof(firewall_rule_t)); rule_ptr->key = ++this->amount_of_rules; - strncpy(rule_ptr->source, source.c_str(), sizeof(rule_ptr->source)); - strncpy(rule_ptr->destination, destination.c_str(), sizeof(rule_ptr->destination)); - rule_ptr->port_from = port_from.toInt(); - rule_ptr->port_to = port_to.toInt(); - rule_ptr->protocol = string_to_protocol(protocol); - rule_ptr->target = string_to_target(target); + strncpy(rule_ptr->ip, args[IP].c_str(), sizeof(rule_ptr->ip)); + rule_ptr->port_from = args[PORT_FROM].toInt(); + rule_ptr->port_to = args[PORT_TO].toInt(); + rule_ptr->protocol = string_to_protocol(args[PROTOCOL]); + rule_ptr->target = string_to_target(args[TARGET]); add_rule_to_firewall(rule_ptr); return rule_ptr; @@ -116,7 +115,7 @@ namespace fw firewall_rule_t *rule_ptr = this->rule_head; while (rule_ptr != NULL) { - if (strncmp(ip, rule_ptr->source, IPV4ADDRESS_LENGTH) == 0) + if (strncmp(ip, rule_ptr->ip, IPV4ADDRESS_LENGTH) == 0) { if (rule_ptr->port_from <= port && port <= rule_ptr->port_to) return true; diff --git a/ESPFirewall/lib/Firewall/src/Firewall.hpp b/ESPFirewall/lib/Firewall/src/Firewall.hpp index 59976f6..eeb6b9c 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.hpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.hpp @@ -15,7 +15,7 @@ namespace fw firewall_rule_t *get_rule_head(); void add_rule_to_firewall(firewall_rule_t *rule_ptr, const bool save_in_eeprom = true); - firewall_rule_t *add_rule_to_firewall(String source, String destination, String port_from, String port_to, String protocol, String target); + firewall_rule_t *add_rule_to_firewall(String *args); firewall_rule_t *get_rule_from_firewall(const uint8_t key); ok_t delete_rule_from_firewall(const uint8_t key); diff --git a/ESPFirewall/lib/Firewall/src/Storage.cpp b/ESPFirewall/lib/Firewall/src/Storage.cpp index f4e56c2..5b7acc0 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.cpp +++ b/ESPFirewall/lib/Firewall/src/Storage.cpp @@ -25,8 +25,7 @@ namespace fw #ifdef ESP8266 firewall_rule_t rule; uint8_t total_space_needed = 0; - total_space_needed += sizeof(rule.source); - total_space_needed += sizeof(rule.destination); + total_space_needed += sizeof(rule.ip); total_space_needed += sizeof(rule.port_from); total_space_needed += sizeof(rule.port_to); total_space_needed += sizeof(rule.target); @@ -87,26 +86,20 @@ namespace fw sprintf(rulename, "fwRule%i", key); this->memory.begin(rulename, true); - strncpy(rule_ptr->source, this->memory.getString("source", "0.0.0.0").c_str(), sizeof(rule_ptr->source)); - strncpy(rule_ptr->destination, this->memory.getString("destination", "0.0.0.0").c_str(), sizeof(rule_ptr->source)); - rule_ptr->port_from = this->memory.getUChar("port_from", 0); - rule_ptr->port_to = this->memory.getUChar("port_to", 0); - rule_ptr->protocol = static_cast(this->memory.getUChar("protocol", PROTOCOL_ALL)); - rule_ptr->target = static_cast(this->memory.getUChar("target", TARGET_REJECT)); + strncpy(rule_ptr->source, this->memory.getString(firewall_fields[IP], "0.0.0.0").c_str(), sizeof(rule_ptr->source)); + rule_ptr->port_from = this->memory.getUChar(firewall_fields[PORT_FROM], 0); + rule_ptr->port_to = this->memory.getUChar(firewall_fields[PORT_TO], 0); + rule_ptr->protocol = static_cast(this->memory.getUChar(firewall_fields[PROTOCOL], PROTOCOL_ALL)); + rule_ptr->target = static_cast(this->memory.getUChar(firewall_fields[TARGET], TARGET_REJECT)); this->memory.end(); #elif defined(ESP8266) uint16_t eespom_position = eeprom_rule_position(key); const char source[IPV4ADDRESS_LENGTH] = ""; - const char destination[IPV4ADDRESS_LENGTH] = ""; EEPROM.get(eespom_position, source); - strncpy(rule_ptr->source, source, sizeof(rule_ptr->source)); - eespom_position += sizeof(rule_ptr->source); - - EEPROM.get(eespom_position, destination); - strncpy(rule_ptr->destination, destination, sizeof(rule_ptr->destination)); - eespom_position += sizeof(rule_ptr->destination); + strncpy(rule_ptr->ip, source, sizeof(rule_ptr->ip)); + eespom_position += sizeof(rule_ptr->ip); rule_ptr->port_from = EEPROM.read(eespom_position); eespom_position += sizeof(rule_ptr->port_from); @@ -141,21 +134,18 @@ namespace fw sprintf(rulename, "fwRule%i", rule_ptr->key); this->memory.begin(rulename, false); - this->memory.putString("source", rule_ptr->source); - this->memory.putString("destination", rule_ptr->destination); - this->memory.putUChar("port_from", rule_ptr->port_from); - this->memory.putUChar("port_to", rule_ptr->port_to); - this->memory.putUChar("protocol", rule_ptr->protocol); - this->memory.putUChar("target", rule_ptr->target); + this->memory.putString(firewall_fields[IP], rule_ptr->ip); + this->memory.putUChar(firewall_fields[PORT_FROM], rule_ptr->port_from); + this->memory.putUChar(firewall_fields[PORT_TO], rule_ptr->port_to); + this->memory.putUChar(firewall_fields[PROTOCOL], rule_ptr->protocol); + this->memory.putUChar(firewall_fields[TARGET], rule_ptr->target); this->memory.end(); #elif defined(ESP8266) uint16_t eespom_position = eeprom_rule_position(rule_ptr->key); - EEPROM.put(eespom_position, rule_ptr->source); - eespom_position += sizeof(rule_ptr->source); - EEPROM.put(eespom_position, rule_ptr->destination); - eespom_position += sizeof(rule_ptr->destination); + EEPROM.put(eespom_position, rule_ptr->ip); + eespom_position += sizeof(rule_ptr->ip); EEPROM.put(eespom_position, rule_ptr->port_from); eespom_position += sizeof(rule_ptr->port_from); EEPROM.put(eespom_position, rule_ptr->port_to); diff --git a/ESPFirewall/lib/Firewall/src/Utils.hpp b/ESPFirewall/lib/Firewall/src/Utils.hpp index ec19025..b7f1426 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.hpp +++ b/ESPFirewall/lib/Firewall/src/Utils.hpp @@ -37,8 +37,7 @@ namespace fw typedef struct firewall_rules { uint8_t key; - char source[IPV4ADDRESS_LENGTH]; - char destination[IPV4ADDRESS_LENGTH]; + char ip[IPV4ADDRESS_LENGTH]; uint32_t port_from; // port can be max 65565 uint32_t port_to; // range of uint16_t: 0 to 65535 firewall_protocol_t protocol; @@ -46,15 +45,22 @@ namespace fw struct firewall_rules *next; } firewall_rule_t; - static const uint8_t firewall_fields_amount = 6; - const char firewall_fields[firewall_fields_amount][12] = { - "source", - "destination", + static const uint8_t firewall_fields_amount = 5; + const char firewall_fields[firewall_fields_amount][10] = { + "ip", "port_from", "port_to", "protocol", "target", }; + typedef enum firewall_fields : uint8_t + { + IP, + PORT_FROM, + PORT_TO, + PROTOCOL, + TARGET, + } firewall_fields_t; static const uint8_t CREDENTIALS_LENGTH = 32; typedef struct credentials @@ -65,7 +71,7 @@ namespace fw typedef struct api_endpoints { - char uri[40]; + char uri[60]; char method[7]; char description[30]; struct api_endpoints *next; From 6461b71799a39a846af6cb9adea59aaf8328ecb7 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Sun, 12 Jun 2022 11:07:55 +0200 Subject: [PATCH 17/23] Work in Progress on storage --- ESPFirewall/lib/Firewall/src/Storage.cpp | 27 ++++++++++++------------ ESPFirewall/lib/Firewall/src/Storage.hpp | 7 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Storage.cpp b/ESPFirewall/lib/Firewall/src/Storage.cpp index 5b7acc0..4ae2849 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.cpp +++ b/ESPFirewall/lib/Firewall/src/Storage.cpp @@ -4,36 +4,35 @@ namespace fw { Storage::Storage() { -#ifdef ESP8266 +#ifdef ESP32 +#elif defined(ESP8266) this->setup_eeprom(); #endif } Storage::~Storage() { +#ifdef ESP32 +#elif defined(ESP8266) +#endif } void Storage::setup_eeprom() { -#ifdef ESP8266 +#ifdef ESP32 +#elif defined(ESP8266) EEPROM.begin(this->eeprom_size); #endif } uint16_t Storage::eeprom_rule_position(uint8_t key) { -#ifdef ESP8266 - firewall_rule_t rule; - uint8_t total_space_needed = 0; - total_space_needed += sizeof(rule.ip); - total_space_needed += sizeof(rule.port_from); - total_space_needed += sizeof(rule.port_to); - total_space_needed += sizeof(rule.target); - total_space_needed += sizeof(rule.protocol); - // key-1 because key will be in range 1-255, but we need 1 less for multiplication - return eeprom_rules_head + (key - 1) * total_space_needed; -#elif defined(ESP32) +#ifdef ESP32 return 0; +#elif defined(ESP8266) + uint8_t total_space_needed = sizeof(firewall_rule_t); + // key will be in range 1-255, but we need 1 less for multiplication to work + return eeprom_rules_head + (key - 1) * total_space_needed; #endif } @@ -48,7 +47,7 @@ namespace fw return value; #elif defined(ESP8266) - if (strncmp("amount_of_rules", key, 16) == 0) + if (strncmp(amount, key, sizeof(amount)) == 0) { uint8_t security_number = EEPROM.read(this->eeprom_settings_head); uint8_t amount_of_rules = EEPROM.read(this->eeprom_amout_of_rules_head); diff --git a/ESPFirewall/lib/Firewall/src/Storage.hpp b/ESPFirewall/lib/Firewall/src/Storage.hpp index 1f44da4..395733b 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.hpp +++ b/ESPFirewall/lib/Firewall/src/Storage.hpp @@ -21,13 +21,14 @@ namespace fw #ifdef ESP32 Preferences memory; #elif defined(ESP8266) - // Storage per firewall rule is 42 Byte - // Space for 15 Rules is 630 Byte plus 10 byte for settings - const uint16_t eeprom_size = 640; + // Space for 15 Rules plus 10 byte for settings + const uint16_t eeprom_size = 15 * sizeof(firewall_rule_t) + 10; + // Ramdon security number to check if settings have been written by this const uint8_t security_number = 93; const uint16_t eeprom_settings_head = 0; const uint16_t eeprom_amout_of_rules_head = eeprom_settings_head + 1; const uint16_t eeprom_rules_head = 10; + const char *amount = "amount_of_rules"; #endif void setup_eeprom(); uint16_t eeprom_rule_position(uint8_t key); From f757b062350544f94f277df30639a1b628452fd3 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Sun, 12 Jun 2022 13:40:58 +0200 Subject: [PATCH 18/23] Major cleanup, looking at it after break --- ESPFirewall/lib/Firewall/library.json | 11 --- ESPFirewall/lib/Firewall/src/API.cpp | 31 ++++---- ESPFirewall/lib/Firewall/src/API.hpp | 3 +- ESPFirewall/lib/Firewall/src/Firewall.cpp | 6 +- ESPFirewall/lib/Firewall/src/Storage.cpp | 87 +++++++--------------- ESPFirewall/lib/Firewall/src/Storage.hpp | 20 ++--- ESPFirewall/lib/Firewall/src/Utils.cpp | 89 ----------------------- ESPFirewall/lib/Firewall/src/Utils.hpp | 11 +-- 8 files changed, 55 insertions(+), 203 deletions(-) delete mode 100644 ESPFirewall/lib/Firewall/library.json diff --git a/ESPFirewall/lib/Firewall/library.json b/ESPFirewall/lib/Firewall/library.json deleted file mode 100644 index bec6af0..0000000 --- a/ESPFirewall/lib/Firewall/library.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "firewall", - "license": "MIT", - "version": "0.0.1", - "frameworks": "arduino", - "platforms": ["espressif32"], - "dependencies": { - "bblanchon/ArduinoJson": "^6.19.4", - "external-repo": "https://github.com/fhessel/esp32_https_server/pull/91" - } -} diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index e01a6ed..a0b4acb 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -123,7 +123,7 @@ namespace fw void API::get_endpoint_list_handler() { - this->json_generic_response(this->construct_json_api(), 200); + this->json_array_response(this->construct_json_api(), 200); } void API::get_firewall_rule_handler() @@ -143,7 +143,7 @@ namespace fw { if (this->check_auth() == DENIED) return; - this->json_generic_response(this->construct_json_firewall(), 200); + this->json_array_response(this->construct_json_firewall(), 200); } void API::post_firewall_handler() @@ -158,7 +158,7 @@ namespace fw args[i] = this->server->arg(firewall_fields[i]); } firewall_rule_t *rule_ptr = firewall->add_rule_to_firewall(args); - this->json_generic_response(this->construct_json_firewall_rule(rule_ptr), 200); + this->json_generic_response(this->construct_json_firewall_rule(rule_ptr), 201); } else { @@ -186,7 +186,7 @@ namespace fw { for (uint8_t i = 0; i < firewall_fields_amount; i++) { - if (!this->server->hasArg(firewall_fields[i])) + if (i != KEY && !this->server->hasArg(firewall_fields[i])) return false; } return true; @@ -209,24 +209,26 @@ namespace fw void API::json_generic_response(String serialized_string, const uint16_t response_code) { - this->server->send( - response_code, - "application/json; charset=utf-8", - construct_json_begin(response_code) + "\"result\": [" + serialized_string + "]}"); + this->server->send(response_code, json_response_type, serialized_string); + } + + void API::json_array_response(String serialized_string, const uint16_t response_code) + { + this->server->send(response_code, json_response_type, "[" + serialized_string + "]"); } void API::json_message_response(String message, const uint16_t response_code) { - String serialized_string = construct_json_begin(response_code); + String serialized_string = "{"; serialized_string += json_new_attribute("message", message, true); serialized_string += "}"; - this->server->send(response_code, "application/json; charset=utf-8", serialized_string); + this->server->send(response_code, json_response_type, serialized_string); } String API::construct_json_firewall_rule(firewall_rule_t *rule_ptr) { String serialized_string = "{"; - serialized_string += json_new_attribute("key", rule_ptr->key); + serialized_string += json_new_attribute(firewall_fields[KEY], rule_ptr->key); serialized_string += json_new_attribute(firewall_fields[IP], rule_ptr->ip); serialized_string += json_new_attribute(firewall_fields[PORT_FROM], rule_ptr->port_from); serialized_string += json_new_attribute(firewall_fields[PORT_TO], rule_ptr->port_to); @@ -273,11 +275,4 @@ namespace fw } return serialized_string; } - - String API::construct_json_begin(const uint16_t response_code) - { - String serialized_string = "{"; - serialized_string += json_new_attribute("status", response_code_to_string(response_code)); - return serialized_string; - } } diff --git a/ESPFirewall/lib/Firewall/src/API.hpp b/ESPFirewall/lib/Firewall/src/API.hpp index d3339da..ee50ed2 100644 --- a/ESPFirewall/lib/Firewall/src/API.hpp +++ b/ESPFirewall/lib/Firewall/src/API.hpp @@ -32,6 +32,7 @@ namespace fw api_endpoint_t *endpoint_head = NULL; String api_ip = "0.0.0.0"; uint16_t api_port; + String json_response_type = "application/json; charset=utf-8"; String get_url_base(); ok_t setup_auth(const char *username, const char *password); @@ -50,13 +51,13 @@ namespace fw String json_new_attribute(String key, String value, bool last = false); String json_new_attribute(String key, uint32_t value, bool last = false); void json_generic_response(String serialized_string, const uint16_t response_code); + void json_array_response(String serialized_string, const uint16_t response_code); void json_message_response(String message, const uint16_t response_code); String construct_json_firewall_rule(firewall_rule_t *rule_ptr); String construct_json_firewall(); String construct_json_api_endpoint(api_endpoint_t *api_ptr); String construct_json_api(); - String construct_json_begin(const uint16_t response_code); }; } diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp index 7bcb501..c304219 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.cpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -4,7 +4,7 @@ namespace fw { Firewall::Firewall() { - this->amount_of_rules = retrieve_settings_value("amount_of_rules"); + this->amount_of_rules = retrieve_amount_of_rules(); for (uint8_t i = 1; i <= this->amount_of_rules; i++) { firewall_rule_t *rule_ptr = retrieve_firewall_rule(i); @@ -23,7 +23,7 @@ namespace fw void Firewall::add_rule_to_firewall(firewall_rule_t *rule_ptr, const bool save_in_eeprom) { - store_settings_value("amount_of_rules", this->amount_of_rules); + store_amount_of_rules(this->amount_of_rules); if (save_in_eeprom) Storage::store_firewall_rule(rule_ptr); if (this->rule_head == NULL) @@ -104,7 +104,7 @@ namespace fw } free(current_rule); this->amount_of_rules--; - Storage::store_settings_value("amount_of_rules", this->amount_of_rules); + Storage::store_amount_of_rules(this->amount_of_rules); if (this->amount_of_rules != 0) Storage::store_all_firewall_rules(rule_head); return SUCCESS; diff --git a/ESPFirewall/lib/Firewall/src/Storage.cpp b/ESPFirewall/lib/Firewall/src/Storage.cpp index 4ae2849..48a8b28 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.cpp +++ b/ESPFirewall/lib/Firewall/src/Storage.cpp @@ -4,25 +4,17 @@ namespace fw { Storage::Storage() { -#ifdef ESP32 -#elif defined(ESP8266) - this->setup_eeprom(); +#if defined(ESP8266) + this->max_rules = 15; + this->eeprom_amount_of_rules = 0; + this->eeprom_rules_head = 1; + this->eeprom_size = this->max_rules * sizeof(firewall_rule_t) + eeprom_rules_head; + EEPROM.begin(this->eeprom_size); #endif } Storage::~Storage() { -#ifdef ESP32 -#elif defined(ESP8266) -#endif - } - - void Storage::setup_eeprom() - { -#ifdef ESP32 -#elif defined(ESP8266) - EEPROM.begin(this->eeprom_size); -#endif } uint16_t Storage::eeprom_rule_position(uint8_t key) @@ -30,49 +22,36 @@ namespace fw #ifdef ESP32 return 0; #elif defined(ESP8266) - uint8_t total_space_needed = sizeof(firewall_rule_t); - // key will be in range 1-255, but we need 1 less for multiplication to work - return eeprom_rules_head + (key - 1) * total_space_needed; + return eeprom_rules_head + (key - 1) * sizeof(firewall_rule_t); #endif } - uint8_t Storage::retrieve_settings_value(const char *key) + uint8_t Storage::retrieve_amount_of_rules() { #ifdef ESP32 - uint8_t value; - this->memory.begin("settings", true); - value = memory.getUChar(key, 0); + const uint8_t value = memory.getUChar("amount_of_rules", 0); this->memory.end(); return value; #elif defined(ESP8266) - if (strncmp(amount, key, sizeof(amount)) == 0) - { - uint8_t security_number = EEPROM.read(this->eeprom_settings_head); - uint8_t amount_of_rules = EEPROM.read(this->eeprom_amout_of_rules_head); + const uint8_t amount_of_rules = EEPROM.read(this->eeprom_amount_of_rules); - if (amount_of_rules > 50 || security_number != this->security_number) - return 0; - return amount_of_rules; - } - return 0; + if (amount_of_rules > this->max_rules) + return 0; + return amount_of_rules; #endif } - void Storage::store_settings_value(const char *key, const uint8_t new_amount) + void Storage::store_amount_of_rules(const uint8_t new_amount) { #ifdef ESP32 this->memory.begin("settings", false); - this->memory.putUChar(key, new_amount); + this->memory.putUChar("amount_of_rules", new_amount); this->memory.end(); #elif defined(ESP8266) - if (strncmp("amount_of_rules", key, 16) == 0) - { - EEPROM.write(this->eeprom_settings_head, this->security_number); - EEPROM.write(this->eeprom_amout_of_rules_head, new_amount); - EEPROM.commit(); - } + EEPROM.put(this->eeprom_amount_of_rules, new_amount); + EEPROM.commit(); #endif } @@ -94,22 +73,12 @@ namespace fw #elif defined(ESP8266) uint16_t eespom_position = eeprom_rule_position(key); - const char source[IPV4ADDRESS_LENGTH] = ""; - EEPROM.get(eespom_position, source); - strncpy(rule_ptr->ip, source, sizeof(rule_ptr->ip)); - eespom_position += sizeof(rule_ptr->ip); - - rule_ptr->port_from = EEPROM.read(eespom_position); - eespom_position += sizeof(rule_ptr->port_from); - - rule_ptr->port_to = EEPROM.read(eespom_position); - eespom_position += sizeof(rule_ptr->port_to); - - rule_ptr->protocol = static_cast(EEPROM.read(eespom_position)); - eespom_position += sizeof(rule_ptr->protocol); - - rule_ptr->target = static_cast(EEPROM.read(eespom_position)); + EEPROM.get(eespom_position, rule_ptr->ip); + EEPROM.get(eespom_position += sizeof(rule_ptr->ip), rule_ptr->port_from); + EEPROM.get(eespom_position += sizeof(rule_ptr->port_from), rule_ptr->port_to); + EEPROM.get(eespom_position += sizeof(rule_ptr->port_to), rule_ptr->protocol); + EEPROM.get(eespom_position += sizeof(rule_ptr->protocol), rule_ptr->target); #endif return rule_ptr; } @@ -144,14 +113,10 @@ namespace fw uint16_t eespom_position = eeprom_rule_position(rule_ptr->key); EEPROM.put(eespom_position, rule_ptr->ip); - eespom_position += sizeof(rule_ptr->ip); - EEPROM.put(eespom_position, rule_ptr->port_from); - eespom_position += sizeof(rule_ptr->port_from); - EEPROM.put(eespom_position, rule_ptr->port_to); - eespom_position += sizeof(rule_ptr->port_to); - EEPROM.put(eespom_position, rule_ptr->protocol); - eespom_position += sizeof(rule_ptr->protocol); - EEPROM.put(eespom_position, rule_ptr->target); + EEPROM.put(eespom_position += sizeof(rule_ptr->ip), rule_ptr->port_from); + EEPROM.put(eespom_position += sizeof(rule_ptr->port_from), rule_ptr->port_to); + EEPROM.put(eespom_position += sizeof(rule_ptr->port_to), rule_ptr->protocol); + EEPROM.put(eespom_position += sizeof(rule_ptr->protocol), rule_ptr->target); EEPROM.commit(); #endif diff --git a/ESPFirewall/lib/Firewall/src/Storage.hpp b/ESPFirewall/lib/Firewall/src/Storage.hpp index 395733b..26ab44b 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.hpp +++ b/ESPFirewall/lib/Firewall/src/Storage.hpp @@ -21,21 +21,17 @@ namespace fw #ifdef ESP32 Preferences memory; #elif defined(ESP8266) - // Space for 15 Rules plus 10 byte for settings - const uint16_t eeprom_size = 15 * sizeof(firewall_rule_t) + 10; - // Ramdon security number to check if settings have been written by this - const uint8_t security_number = 93; - const uint16_t eeprom_settings_head = 0; - const uint16_t eeprom_amout_of_rules_head = eeprom_settings_head + 1; - const uint16_t eeprom_rules_head = 10; - const char *amount = "amount_of_rules"; -#endif - void setup_eeprom(); + uint8_t max_rules; + uint16_t eeprom_size; + uint16_t eeprom_amount_of_rules; + uint16_t eeprom_rules_head; + uint16_t eeprom_rule_position(uint8_t key); +#endif protected: - uint8_t retrieve_settings_value(const char *key); - void store_settings_value(const char *key, const uint8_t new_amount); + uint8_t retrieve_amount_of_rules(); + void store_amount_of_rules(const uint8_t new_amount); firewall_rule_t *retrieve_firewall_rule(const uint8_t key); void store_all_firewall_rules(firewall_rule_t *rule_head); void store_firewall_rule(firewall_rule_t *rule_ptr); diff --git a/ESPFirewall/lib/Firewall/src/Utils.cpp b/ESPFirewall/lib/Firewall/src/Utils.cpp index e0f1783..e6a2f75 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.cpp +++ b/ESPFirewall/lib/Firewall/src/Utils.cpp @@ -48,95 +48,6 @@ namespace fw return TARGET_ACCEPT; } - String response_code_to_string(const uint16_t response_code) - { - switch (response_code) - { - case 100: - return F("Continue"); - case 101: - return F("Switching Protocols"); - case 200: - return F("OK"); - case 201: - return F("Created"); - case 202: - return F("Accepted"); - case 203: - return F("Non-Authoritative Information"); - case 204: - return F("No Content"); - case 205: - return F("Reset Content"); - case 206: - return F("Partial Content"); - case 300: - return F("Multiple Choices"); - case 301: - return F("Moved Permanently"); - case 302: - return F("Found"); - case 303: - return F("See Other"); - case 304: - return F("Not Modified"); - case 305: - return F("Use Proxy"); - case 307: - return F("Temporary Redirect"); - case 400: - return F("Bad Request"); - case 401: - return F("Unauthorized"); - case 402: - return F("Payment Required"); - case 403: - return F("Forbidden"); - case 404: - return F("Not Found"); - case 405: - return F("Method Not Allowed"); - case 406: - return F("Not Acceptable"); - case 407: - return F("Proxy Authentication Required"); - case 408: - return F("Request Time-out"); - case 409: - return F("Conflict"); - case 410: - return F("Gone"); - case 411: - return F("Length Required"); - case 412: - return F("Precondition Failed"); - case 413: - return F("Request Entity Too Large"); - case 414: - return F("Request-URI Too Large"); - case 415: - return F("Unsupported Media Type"); - case 416: - return F("Requested range not satisfiable"); - case 417: - return F("Expectation Failed"); - case 500: - return F("Internal Server Error"); - case 501: - return F("Not Implemented"); - case 502: - return F("Bad Gateway"); - case 503: - return F("Service Unavailable"); - case 504: - return F("Gateway Time-out"); - case 505: - return F("HTTP Version not supported"); - default: - return F(""); - } - } - void endless_loop() { Serial.printf("Something went wrong. Running endless loop until fixed..."); diff --git a/ESPFirewall/lib/Firewall/src/Utils.hpp b/ESPFirewall/lib/Firewall/src/Utils.hpp index b7f1426..95631e4 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.hpp +++ b/ESPFirewall/lib/Firewall/src/Utils.hpp @@ -45,16 +45,11 @@ namespace fw struct firewall_rules *next; } firewall_rule_t; - static const uint8_t firewall_fields_amount = 5; - const char firewall_fields[firewall_fields_amount][10] = { - "ip", - "port_from", - "port_to", - "protocol", - "target", - }; + static const uint8_t firewall_fields_amount = 6; + const char firewall_fields[firewall_fields_amount][10] = {"key", "ip", "port_from", "port_to", "protocol", "target"}; typedef enum firewall_fields : uint8_t { + KEY, IP, PORT_FROM, PORT_TO, From 2e474d8e2a0499a43a37f5118717933076637c0a Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Sun, 12 Jun 2022 14:21:06 +0200 Subject: [PATCH 19/23] Fix esp32 --- ESPFirewall/lib/Firewall/src/Storage.cpp | 2 +- ESPFirewall/lib/Firewall/src/Storage.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Storage.cpp b/ESPFirewall/lib/Firewall/src/Storage.cpp index 48a8b28..b2f366f 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.cpp +++ b/ESPFirewall/lib/Firewall/src/Storage.cpp @@ -64,7 +64,7 @@ namespace fw sprintf(rulename, "fwRule%i", key); this->memory.begin(rulename, true); - strncpy(rule_ptr->source, this->memory.getString(firewall_fields[IP], "0.0.0.0").c_str(), sizeof(rule_ptr->source)); + strncpy(rule_ptr->ip, this->memory.getString(firewall_fields[IP], "0.0.0.0").c_str(), sizeof(rule_ptr->ip)); rule_ptr->port_from = this->memory.getUChar(firewall_fields[PORT_FROM], 0); rule_ptr->port_to = this->memory.getUChar(firewall_fields[PORT_TO], 0); rule_ptr->protocol = static_cast(this->memory.getUChar(firewall_fields[PROTOCOL], PROTOCOL_ALL)); diff --git a/ESPFirewall/lib/Firewall/src/Storage.hpp b/ESPFirewall/lib/Firewall/src/Storage.hpp index 26ab44b..ec69548 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.hpp +++ b/ESPFirewall/lib/Firewall/src/Storage.hpp @@ -26,8 +26,8 @@ namespace fw uint16_t eeprom_amount_of_rules; uint16_t eeprom_rules_head; - uint16_t eeprom_rule_position(uint8_t key); #endif + uint16_t eeprom_rule_position(uint8_t key); protected: uint8_t retrieve_amount_of_rules(); From 56a74f912110994ed8fd4bdb78a2ebde9580a40d Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Sun, 12 Jun 2022 14:21:18 +0200 Subject: [PATCH 20/23] use args for python test script --- ESPFirewall/app.py | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/ESPFirewall/app.py b/ESPFirewall/app.py index 63d0cf1..021383d 100644 --- a/ESPFirewall/app.py +++ b/ESPFirewall/app.py @@ -1,11 +1,36 @@ -import socket - -sock = socket.socket() - -host = "10.93.0.246" -port = 80 - -sock.connect((host, port)) -sock.send("test".encode()) -sock.close() +import socket +import sys +import getopt +import argparse + +def main(argv): + parser = argparse.ArgumentParser( + description='Send socket message to ip and port.') + parser.add_argument('-i', '--ip', + default='localhost', + dest='ip', + help='Provide destination ip. Defaults to localhost', + type=str + ) + parser.add_argument('-p', '--port', + default=80, + dest='port', + help='Provide destination port. Defaults to 80', + type=int + ) + + args = parser.parse_args() + print(f'Sending message to {args.ip}:{args.port}') + sock = socket.socket() + try: + sock.connect((args.ip, args.port)) + sock.send("test".encode()) + print("Message sent.") + sock.close() + except: + print("Cannot send message...") + + +if __name__ == "__main__": + main(sys.argv[1:]) From 8353443ea431b4fb36b2370052b6f3f1ffc7e875 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Sun, 12 Jun 2022 14:26:07 +0200 Subject: [PATCH 21/23] Ports need more storage in eeprom --- ESPFirewall/lib/Firewall/src/Storage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Storage.cpp b/ESPFirewall/lib/Firewall/src/Storage.cpp index b2f366f..4504ae4 100644 --- a/ESPFirewall/lib/Firewall/src/Storage.cpp +++ b/ESPFirewall/lib/Firewall/src/Storage.cpp @@ -65,8 +65,8 @@ namespace fw this->memory.begin(rulename, true); strncpy(rule_ptr->ip, this->memory.getString(firewall_fields[IP], "0.0.0.0").c_str(), sizeof(rule_ptr->ip)); - rule_ptr->port_from = this->memory.getUChar(firewall_fields[PORT_FROM], 0); - rule_ptr->port_to = this->memory.getUChar(firewall_fields[PORT_TO], 0); + rule_ptr->port_from = this->memory.getULong(firewall_fields[PORT_FROM], 0); + rule_ptr->port_to = this->memory.getULong(firewall_fields[PORT_TO], 0); rule_ptr->protocol = static_cast(this->memory.getUChar(firewall_fields[PROTOCOL], PROTOCOL_ALL)); rule_ptr->target = static_cast(this->memory.getUChar(firewall_fields[TARGET], TARGET_REJECT)); this->memory.end(); @@ -103,8 +103,8 @@ namespace fw this->memory.begin(rulename, false); this->memory.putString(firewall_fields[IP], rule_ptr->ip); - this->memory.putUChar(firewall_fields[PORT_FROM], rule_ptr->port_from); - this->memory.putUChar(firewall_fields[PORT_TO], rule_ptr->port_to); + this->memory.putULong(firewall_fields[PORT_FROM], rule_ptr->port_from); + this->memory.putULong(firewall_fields[PORT_TO], rule_ptr->port_to); this->memory.putUChar(firewall_fields[PROTOCOL], rule_ptr->protocol); this->memory.putUChar(firewall_fields[TARGET], rule_ptr->target); From b3d9c2a6468de1873f3eb1d63b1ca9168dd5a95c Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Sun, 12 Jun 2022 14:58:24 +0200 Subject: [PATCH 22/23] Write some helpers to compare --- ESPFirewall/lib/Firewall/src/Firewall.cpp | 19 +++++++------------ ESPFirewall/lib/Firewall/src/Firewall.hpp | 2 +- ESPFirewall/lib/Firewall/src/Utils.cpp | 5 +++++ ESPFirewall/lib/Firewall/src/Utils.hpp | 1 + 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/ESPFirewall/lib/Firewall/src/Firewall.cpp b/ESPFirewall/lib/Firewall/src/Firewall.cpp index c304219..45c6bf1 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.cpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.cpp @@ -110,16 +110,15 @@ namespace fw return SUCCESS; } - bool Firewall::is_included_in_firewall(const char *ip, const uint16_t port) + bool Firewall::is_included_in_firewall(String &ip, const uint32_t &port) { firewall_rule_t *rule_ptr = this->rule_head; while (rule_ptr != NULL) { - if (strncmp(ip, rule_ptr->ip, IPV4ADDRESS_LENGTH) == 0) - { - if (rule_ptr->port_from <= port && port <= rule_ptr->port_to) - return true; - } + if (ip == String(rule_ptr->ip) && + is_in_range(port, rule_ptr->port_from, rule_ptr->port_to) && + rule_ptr->target != TARGET_ACCEPT) + return true; rule_ptr = rule_ptr->next; } return false; @@ -127,12 +126,8 @@ namespace fw bool Firewall::is_client_allowed(WiFiClient client) { - const char *ip = client.remoteIP().toString().c_str(); - const uint16_t port = client.remotePort(); - - Serial.print(client.remoteIP()); - Serial.print(":"); - Serial.println(client.remotePort()); + String ip = client.remoteIP().toString(); + const uint32_t port = client.remotePort(); return !is_included_in_firewall(ip, port); } } diff --git a/ESPFirewall/lib/Firewall/src/Firewall.hpp b/ESPFirewall/lib/Firewall/src/Firewall.hpp index eeb6b9c..47cc64d 100644 --- a/ESPFirewall/lib/Firewall/src/Firewall.hpp +++ b/ESPFirewall/lib/Firewall/src/Firewall.hpp @@ -19,7 +19,7 @@ namespace fw firewall_rule_t *get_rule_from_firewall(const uint8_t key); ok_t delete_rule_from_firewall(const uint8_t key); - bool is_included_in_firewall(const char *ip, const uint16_t port); + bool is_included_in_firewall(String &ip, const uint32_t &port); bool is_client_allowed(WiFiClient client); protected: diff --git a/ESPFirewall/lib/Firewall/src/Utils.cpp b/ESPFirewall/lib/Firewall/src/Utils.cpp index e6a2f75..9be85ba 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.cpp +++ b/ESPFirewall/lib/Firewall/src/Utils.cpp @@ -54,4 +54,9 @@ namespace fw while (true) delay(500); } + + bool is_in_range(const uint32_t number, const uint32_t lower, const uint32_t upper) + { + return lower <= number && number <= upper; + } } diff --git a/ESPFirewall/lib/Firewall/src/Utils.hpp b/ESPFirewall/lib/Firewall/src/Utils.hpp index 95631e4..db8e5d5 100644 --- a/ESPFirewall/lib/Firewall/src/Utils.hpp +++ b/ESPFirewall/lib/Firewall/src/Utils.hpp @@ -78,6 +78,7 @@ namespace fw firewall_target_t string_to_target(String &target); String response_code_to_string(const uint16_t response_code); void endless_loop(); + bool is_in_range(const uint32_t number, const uint32_t lower, const uint32_t upper); } #endif From c7018d251fca4348bc1447db83ec988689e58ff3 Mon Sep 17 00:00:00 2001 From: Florian Hoss Date: Tue, 19 Jul 2022 10:15:23 +0200 Subject: [PATCH 23/23] Update unauthorised messages --- ESPFirewall/lib/Firewall/src/API.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESPFirewall/lib/Firewall/src/API.cpp b/ESPFirewall/lib/Firewall/src/API.cpp index a0b4acb..5fefc17 100644 --- a/ESPFirewall/lib/Firewall/src/API.cpp +++ b/ESPFirewall/lib/Firewall/src/API.cpp @@ -64,7 +64,7 @@ namespace fw } else { - this->json_message_response("please provide username and password", 403); + this->json_message_response("unauthorised", 403); return DENIED; } }