This repository has been archived on 2024-10-30. You can view files and clone it, but cannot push or open issues or pull requests.
esp-firewall/ESPFirewall/lib/Firewall/docs/firewall/firewall.tex

166 lines
5.5 KiB
TeX
Raw Normal View History

2022-07-19 11:54:39 +02:00
\section{Firewall}
2022-07-20 14:57:17 +02:00
\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
2022-07-19 11:54:39 +02:00
\subsection{Parameter}
2022-07-20 14:57:17 +02:00
After analyzing existing solutions following firewall parameters were implemented:
\lstset{style=c++}
\begin{lstlisting}
typedef enum firewall_targets : uint8_t
{
TARGET_REJECT = 0,
TARGET_DROP = 1,
TARGET_ACCEPT = 2,
} firewall_target_t;
typedef enum firewall_protocols : uint8_t
{
PROTOCOL_TCP = 0,
PROTOCOL_UDP = 1,
PROTOCOL_ALL = 255,
} firewall_protocol_t;
static const uint8_t IPV4ADDRESS_LENGTH = 16;
typedef struct firewall_rules
{
uint8_t key;
char ip[IPV4ADDRESS_LENGTH];
uint32_t port_from;
uint32_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 65565, therefore cannot be of type \verb|uint16_t| but \verb|uint32_t|. Target as well as protocol are enums for the available options. 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.
2022-07-20 15:39:15 +02:00
\subsection{WiFi Events}
To intercept network packages there is a need to somehow get notified when a new package arrived that needs to be analyzed. Based on the firewall rules, it can pass, gets dropped or rejected.
Available ESP32 WiFi Events can be seen in figure \ref*{fig:WiFi Events}. None of those events support reading incoming packages.
\begin{figure}[H]
\begin{center}
\includegraphics[height=0.9\textheight]{wifi-events}
\caption{WiFi Events}
\label{fig:WiFi Events}
\end{center}
\end{figure}
\cite[cf.][]{espressif-wifi}
\subsection{WiFi Buffer Usage}
Looking at the usage of the DMA buffer (Figure \ref{fig:WiFi Buffer}) of the driver we can see where we have to check for received packages.
\begin{figure}[H]
\begin{center}
\includegraphics[width=0.8\textwidth]{wifi-buffer}
\caption{WiFi Buffer}
\label{fig:WiFi Buffer}
\end{center}
\end{figure}
\cite[cf.][]{espressif-wifi}
2022-07-20 16:55:59 +02:00
\subsection{Wi-Fi Sniffer Mode}
Esp32 can be setup in a ``sniffer mode''. Following packets can be dumped to the application:
\begin{list}{-}{}
\item 802.11 Management frame.
\item 802.11 Data frame, including MPDU, AMPDU, and AMSDU.
\item 802.11 MIMO frame, for MIMO frame, the sniffer only dumps the length of the frame.
\item 802.11 Control frame.
\item 802.11 CRC error frame.
\end{list}
The same can be done with the esp8266 as described in this article:
\href{https://carvesystems.com/news/writing-a-simple-esp8266-based-sniffer/}{https://carvesystems.com/news/writing-a-simple-esp8266-based-sniffer/}
2022-07-25 12:38:22 +02:00
\newpage
\subsection{IwIP}
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}
\subsubsection{Analysing}
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("PROTO", "%3" U16_F, (u16_t)IPH_PROTO(iphdr));
ESP_LOGI("IP", "% " U16_F "% " U16_F "% " U16_F "% " U16_F,
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 (97535) PROTO: 1
I (97535) IP: 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.
\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 (1777105) PROTO: 6
I (1777105) IP: 10 93 0 211
I (1779825) PROTO: 17
I (1779825) IP: 10 93 0 211
\end{verbatim}
Looking at the printed protocols this means 6 == "TCP" and 17 == "UDP".
\subsubsection{Using Hook}
2022-07-19 11:54:39 +02:00
\subsection{Benchmark}