\section{Firewall}

\subsection{Software Firewall}

A software firewall is inspecting data that goes in and out of the device. It has to be installed on each device in the network. Therefore, can only protect one device at a time. Looking at already existing solutions for linux and other operating systems, rules and settings can be identified that need to be implemented for this firewall.

\subsection{UFW (Uncomplicated Firewall)}

To see how a firewall works, UFW was analyzed. A look at the table provides following information:

\begin{figure}[H]
    \begin{center} 
        \includegraphics[width=0.6\textwidth]{ufw}
        \caption{UFW}
        \label{fig:UFW}
    \end{center}
\end{figure}

A destination port on the device, the action of the firewall and the IP-Address from where the request originated can be setup. Also the protocol that the rule applies to, can be chosen with TCP or UDP.

\newpage

\subsection{Parameter}

After analyzing existing solutions following firewall parameters were implemented:

\lstset{style=c++}
\begin{lstlisting}
    typedef enum firewall_targets : uint8_t
    {
        TARGET_DROP = 1,
        TARGET_ACCEPT = 2,
    } firewall_target_t;

    typedef enum firewall_protocols : uint8_t
    {
        PROTOCOL_TCP = 6,
        PROTOCOL_UDP = 17,
        PROTOCOL_ALL = 255,
    } firewall_protocol_t;

    static const uint8_t IPV4ADDRESS_LENGTH = 16;
    typedef struct firewall_rules
    {
        uint8_t key;
        char ip[IPV4ADDRESS_LENGTH];
        uint16_t port_from;
        uint16_t port_to;
        firewall_protocol_t protocol;
        firewall_target_t target;
        struct firewall_rules *next;
    } firewall_rule_t;
\end{lstlisting}

A port can be a maximum of 65535, and was chosen because LwIP (Section \ref{lwip}) uses it for the ports in the respective header. Target as well as protocol are enums for the available options. LwIP uses the same specified values for their protocols (Section \ref{lwip_analysis}). To block a range of ports, there is a \verb|port_from| and \verb|port_to|. The firewall will store all the rules as linked list to dynamically add and remove rules.

\subsection{IwIP} \label{lwip}

lwIP is a small independent implementation of the TCP/IP protocol suite and is used in the esp-core for network communication. This is the place the firewall need to check for the incoming traffic in order to drop, reject or pass packets based on the rules.

\cite[cf.][]{lwip}

\newpage

\subsubsection{Analysing} \label{lwip_analysis}

First step is to analyze the code to find out where the packets are getting handled. Looking in 

\verb|~/.platformio/packages/framework-espidf/components/lwip/lwip/src/core/ipv4|

there is a function:

\verb|err_t ip4_input(struct pbuf *p, struct netif *inp)|

to consume all incoming packages. Simply placing a logger can quickly show that this is the place to put the firewall filter.

\begin{verbatim}
if (ip4_addr4_16_val(iphdr->src) == 211)
{
    ESP_LOGI("HOOK", "%3" U16_F, "% " U16_F "% " U16_F "% " U16_F "% " U16_F,
            (u16_t)IPH_PROTO(iphdr)
            ip4_addr1_16_val(iphdr->src),
            ip4_addr2_16_val(iphdr->src),
            ip4_addr3_16_val(iphdr->src),
            ip4_addr4_16_val(iphdr->src));
}
\end{verbatim}

Following output can be seen when sending a ping from the machine with IP-Address \verb|10.93.0.211| to the esp. ICMP is therefore marked with protocol 1.

\begin{verbatim}
    I (x) HOOK:   1 10 93 0 211
\end{verbatim}

Sending a UDP or TCP package to the ESP (IP-Address: \verb|10.93.0.246|) can be done by executing the python code in the repository, or simply executing an nmap\footnote{\href{https://nmap.org/}{https://nmap.org/}} scan with UDP and TCP.

\begin{verbatim}
    python3 tester.py -i 10.93.0.246 -p 80 -t TCP
    python3 tester.py -i 10.93.0.246 -p 22 -t UPD
\end{verbatim}

Following output can be registered.

\begin{verbatim}
    I (x) HOOK:   6 10 93 0 211
    I (x) HOOK:  17 10 93 0 211
\end{verbatim}

Looking at the printed protocols this means evidentially:
$$ 1 \equiv "ICMP" $$
$$ 6 \equiv "TCP" $$
$$ 17 \equiv "UDP" $$

\subsubsection{Arduino as an ESP-IDF component}

LwIP needs to be recompiled to register hooks (Section \ref{sec:hooks}). Therefore the following steps are performed to compile our code with Arduino as an ESP-IDF component on an ESP32.

After initializing an empty ESP-IDF project with PlatformIO the \verb|platformio.ini| file would look like this:

\begin{verbatim}
[platformio]
default_envs = esp32

[env:esp32]
platform = espressif32
board = az-delivery-devkit-v4
framework = espidf
monitor_speed = 115200
\end{verbatim}

Following commands need to be executed inside a fresh ESP-IDF project folder, in order to add Arduino into the setup:

\lstset{style=shell}
\begin{lstlisting}
mkdir -p components && \
cd components && \
git clone https://github.com/espressif/arduino-esp32.git arduino && \
cd arduino && \
git submodule update --init --recursive && \
cd ../..
\end{lstlisting}

After successful cloning of the git repository, some changes need to be written into the ESP-IDF config file with the help of \verb|menuconfig|:

\begin{verbatim}
    platformio run --target menuconfig --environment esp32
\end{verbatim}

Navigating to the section Arduino Configuration, usage of setup() and loop() functions can be turned on with the option ``Autostart Arduino setup and loop on boot''.

After these steps Arduino code can be written and executed like expected, but with the advantages of compiling the whole esp32-core with the specified settings and hooks.

\cite[][]{arduino-esp-idf}

\newpage

\subsubsection{Using a Hook} \label{sec:hooks}

After learning the protocols, a hook needs to be registered in order to filter the packets based on our rules. To register the hook that suits our project, \verb|LWIP_HOOK_IP4_INPUT| needs to be set as \verb|build_flag| in the \verb|platformio.ini| file to overwrite it in LwIP. This is an easy way of testing if it works as expected, but should be written in a function for any other use-case.

\begin{verbatim}
build_flags = 
    '-DLWIP_HOOK_IP4_INPUT(pbuf, input_netif)=({ESP_LOGI("HOOK","TEST");0;})'
\end{verbatim}

\cite[cf.][]{lwip}

After the successful test of the logging hook, an implementation of a function is needed in order to integrate it with the firewall API written to change and create rules.

In order to register a function LwIP needs to know where the prototypes are declared. Therefore, in the \verb|platformio.ini| file, the \verb|build_flags| need to be adjusted.

\begin{verbatim}
build_flags = 
    '-Iinclude'
    '-DESP_IDF_LWIP_HOOK_FILENAME="lwip_hooks.h"'
\end{verbatim}

The file \verb|lwip_hooks.h| has the necessary information for LwIP to know how the function will be called.

\lstset{style=c++}
\begin{lstlisting}
int lwip_hook_ip4_input(struct pbuf *pbuf, struct netif *input_netif);
#define LWIP_HOOK_IP4_INPUT lwip_hook_ip4_input    
\end{lstlisting}

After specifying the prototype the function can be placed in the main.cpp file to be compiled and run.

\subsection{Benchmark}
