# Contents [Network Address Translation](#/nat) [Firewalls Overview](#/firewallss) [Packet Filtering Firewalls](#/pfilters) [Stateful Firewalls](#/stateful) [Application Firewalls](#/application) [Tunneling and Evasion](#/evasion)
# Network Address Translation
## Network Address Translation - Allows one IP address to be shared by many devices - Devices behind the NAT have private IPs - Technically, a NAT is on the network level - Doesn't have to come with a firewall, but almost always does - If it's a firewall, it is also on the transport level
# Firewalls Overview
## Firewall types: packet filter ![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image3.png) - Each packet is judged individually based on the packet headers - Does not keep *state* (part of a stream, from an open connection, etc.) - Called a *stateless* firewall - Very fast, very simple
Firewall types: stateful firewall
![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image4.png) - Keeps state (open connections, app type by port, etc.) - New packets are kept until enough are known to make a decision - Outbound: allow any traffic - Inbound: allow only existing connections
Firewall types: application/proxy firewall
![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image5.png) - Unlike the previous two, this inspects the application data - Thus, much slower - Connection terminates at the firewall, and is re-opened to the server - This is different than NAT - Example: image or package proxy server ## Implementing a firewall ![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image6.png) - Firewalls require kernel modules - The Linux kernel has *hooks*, and a kernel module can register a callback function for each hook - That function can modify, discard, etc., each packet
# Packet Filtering Firewalls
## Packet Filtering [![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image3.png)](http://www.cs.virginia.edu/~asb2t/duimg/n07/image3.png) - Does not keep *state* - Generally only looks at the IP packet headers - Very quick - Can do NAT as well - Common example: `iptables` on Linux ## iptables [![](https://upload.wikimedia.org/wikipedia/commons/9/91/Iptables_diagram.png)](https://commons.wikimedia.org/wiki/File:Iptables_diagram.png) - Three *tables*, each with *chains*, each chain has rules: - filter: packet filtering - nat: NAT - mangle: modifying packets (beyond just NAT) ## Firewall policies - Accepted: allowed through - Denied: packet dropped - Rejected: packet dropped, and the source told A rejected rule will notify fuzzers that something "interesting" is on that port; unless you have a reason, use deny instead ``` $ iptables --list Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy DROP) target prot opt source destination DOCKER-USER all -- anywhere anywhere DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED DOCKER all -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT all -- anywhere anywhere Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain DOCKER (1 references) target prot opt source destination Chain DOCKER-ISOLATION-STAGE-1 (1 references) target prot opt source destination DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere RETURN all -- anywhere anywhere Chain DOCKER-ISOLATION-STAGE-2 (1 references) target prot opt source destination DROP all -- anywhere anywhere RETURN all -- anywhere anywhere Chain DOCKER-USER (1 references) target prot opt source destination RETURN all -- anywhere anywhere $ ``` ``` $ iptables --list-rules -P INPUT ACCEPT -P FORWARD DROP -P OUTPUT ACCEPT -N DOCKER -N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-2 -N DOCKER-USER -A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-ISOLATION-STAGE-1 -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -o docker0 -j DOCKER -A FORWARD -i docker0 ! -o docker0 -j ACCEPT -A FORWARD -i docker0 -o docker0 -j ACCEPT -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-1 -j RETURN -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP -A DOCKER-ISOLATION-STAGE-2 -j RETURN -A DOCKER-USER -j RETURN $ ```
# Stateful Firewalls
## Stateful Firewall [![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image4.png)](http://www.cs.virginia.edu/~asb2t/duimg/n07/image4.png) - Keeps track of the *state* of the connections - Typically allows a response when there has been a network request - Slower than packet filters, but faster than the next category - Most common type ## Stateful Firewall [![](images/graphs/nat.webp)](images/graphs/nat.webp) - This NAT example was a stateful firewall ## Connection Tracking - TCP: analyze the SYN-ACK/SYN-ACK, and consider that an open connection - Allows the ACK/SYN response as the initial SYN requested it - UDP: the protocol is not connection oriented - If data comes from a server because of a request, consider it a connection - ICMP: upon a request, consider the response as opening a connection ## `conntrack` Shows the open connections ``` root@outer1:/# conntrack -L tcp 6 115 TIME_WAIT src=192.168.100.101 dst=185.125.190.36 sport=35876 dport=80 src=185.125.190.36 dst=192.168.100.101 sport=80 dport=35876 [ASSURED] mark=0 use=1 udp 17 25 src=192.168.100.101 dst=8.8.8.8 sport=53427 dport=53 src=8.8.8.8 dst=192.168.100.101 sport=53 dport=53427 mark=0 use=1 udp 17 5 src=192.168.100.101 dst=192.168.65.7 sport=53548 dport=53 src=192.168.65.7 dst=192.168.100.101 sport=53 dport=53548 mark=0 use=1 udp 17 5 src=127.0.0.1 dst=127.0.0.11 sport=58457 dport=53 src=127.0.0.11 dst=127.0.0.1 sport=53974 dport=58457 mark=0 use=1 udp 17 25 src=192.168.100.101 dst=8.8.8.8 sport=57031 dport=53 src=8.8.8.8 dst=192.168.100.101 sport=53 dport=57031 mark=0 use=1 udp 17 5 src=192.168.100.101 dst=192.168.65.7 sport=57152 dport=53 src=192.168.65.7 dst=192.168.100.101 sport=53 dport=57152 mark=0 use=1 udp 17 25 src=192.168.100.3 dst=192.168.100.255 sport=137 dport=137 [UNREPLIED] src=192.168.100.255 dst=192.168.100.3 sport=137 dport=137 mark=0 use=1 udp 17 21 src=192.168.100.3 dst=192.168.100.255 sport=138 dport=138 [UNREPLIED] src=192.168.100.255 dst=192.168.100.3 sport=138 dport=138 mark=0 use=1 tcp 6 99 TIME_WAIT src=192.168.100.3 dst=192.168.100.101 sport=54958 dport=22 src=192.168.100.101 dst=192.168.100.3 sport=22 dport=54958 [ASSURED] mark=0 use=1 conntrack v1.4.6 (conntrack-tools): 9 flow entries have been shown. root@outer1:/# ``` ## Connection Tracking - Connection tracking is not a firewall - But a firewall can pay attention to connection tracking - Instead of: ``` iptables -A FORWARD -p tcp -i eth0 ... ``` - Uses `-m conntrack`: ``` iptables -A FORWARD -p tcp -i eth0 -m conntrack ... ``` - This turns `iptables` into a stateful firewall
# Application Firewalls
## Application Firewall ![](http://www.cs.virginia.edu/~asb2t/duimg/n07/image5.png) - Analyzes the data in the application layer - Meaning the *contents* of the TCP packets - Very slow - Useful for proxies - Or to filter out content ## Proxy Servers ![](images/graphs/proxy.webp) - Caches web pages (or any other application) - Multiple users accessing the same web page do not need multiple GETs to the web server - The proxy must look in the HTTP request to see what page is being accessed - Problem: how often to update the copy in the proxy? - Rapidly changing pages have issues - Or pages that depend on cookies or logins ## Proxy Pros and Cons - Pro: less use of external Internet connection - Pro: can limit website content - Con: can limit website content - Con: how often to update? - Con: need a lot of storage to be useful - Con: web browsers don't re-download cached images anyway ## More Useful Proxy Servers - When building (and constantly re-building) Docker images... - You have to `apt install` many packages - Download them each time will take a while, especially on a slow connection - One can run an apt-cache proxy - Then only the newer packages have to be downloaded ## Socket Secure (SOCKS) [![](https://upload.wikimedia.org/wikipedia/commons/thumb/4/4f/Socken_farbig.jpeg/906px-Socken_farbig.jpeg)](https://commons.wikimedia.org/wiki/File:Socken_farbig.jpeg) - Often implemented via a *shim* layer between the application and transport layers - This would be the session layer in the OSI model - SOCKS (Socket Secure) is an Internet protocol that "exchanges network packets between a client and server through a proxy server" - The client needs to have SOCKS support - More on this shortly...
# Tunneling and Evasion
## Already seen: IPsec VPN
- Implemented at the IP level using IPsec - Because the TCP packet is encrypted, the firewall can't be a stateful (port-aware) firewall - IPsec on home gateways is often disabled by default ## Already seen: Application VPN
- Implemented at the *application* level using TLS/SSL, DTLS, or even SSH - Network packets are "intercepted" by the application, sent over the link, and then re-sent from the other side ## Already seen: SSH "VPN" - ssh can redirect a port through an ssh connection; usage: ``` $ ssh -L 8080:server:80 user@server ``` - Connecting to port 8080 on the localhost machine will connect, through the ssh tunnel, to port 80 on the remote server - Pro: easy for anybody to setup and use - Pro: does not need a VPN application - Pro: application level, so less kernel complexity - Con: does not redirect all traffic - Con: slower than other methods ## Ingress versus Egress - Ingress filtering - "Normal" firewall: blocks all ports except for requested data - One can "poke a hole" in this to allow a single port through - Blocks incoming connections - Egress filtering - Blocks data from outside, such as certain websites - Example: the Great Firewall of China - Blocks data from outgoing requests
SSH to bypass ingress firewalls
- To get access to another network behind a firewall ``` ssh -w 0:0 root@server.com \ -o "PermitLocalCommand=yes" \ -o "LocalCommand= ip addr add 192.168.47.0/24 dev tun0 && \ ip link set tun0 up" \ -o "RemoteCommand=ip addr add 192.168.60.0/24 dev tun0 && \ ip link set tun0 up" ``` - This assumes 192.168.47.0/24 is the *remote* (work) network - And 192.168.60.0/24 is the *local* (home) network - The local command is creating a route to the remote machines - The remote command creating a route to the local machines - But the *routing* is not yet configured ## More configuration - Recall that 192.168.47.0/24 is the remote network - And 192.168.60.0.24 is the local network - Local machine: ``` ip route replace 192.168.60.0/24 dev tun0 ip route add
/32 via
``` - This sets the default route for the remote network to the tun0 interface - Unless you are trying to contact the VPN server -- then go through the normal gateway - Lastly, we need to set up NAT on the remote machine
SSH to bypass egress firewalls
- Let's say that [example.com](http://example.com) is blocked - IP address is 93.184.216.34 - Step 1: set up SSH as in the past two slides - Step 2: enter this one rule: ``` ip route add 93.184.216.34/24 dev tun0 ``` - Now all requests to that site will go through the ssh tunnel ## Bypassing Geo-Restriction [![](https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Map_tack_inserted.jpg/768px-Map_tack_inserted.jpg)](https://commons.wikimedia.org/wiki/File:Map_tack_inserted.jpg) - Any VPN will work, as long as the "other side" is within the Geo-restricted area - UVA states you should never, ever, use their VPN to stream videos ## More Better Tunneling [![](https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Tunnel_of_the_Stadium_of_Nemea%2C_Exit%2C_201983.jpg/1024px-Tunnel_of_the_Stadium_of_Nemea%2C_Exit%2C_201983.jpg)](https://commons.wikimedia.org/wiki/File:Tunnel_of_the_Stadium_of_Nemea,_Exit,_201983.jpg) - So far, we have only seen *static* tunnels - Meaning the tunnel forwards to just one location - What if we want multiple locations? And for it to change dynamically? - Solution: SOCKS (Socket Secure) ## SOCKS (Socket Secure) - A "shim" layer between the application and transport layers; in Python: ``` import socks s = socks.socksocket() s.set_proxy(socks.SOCKS5, "localhost", 4760) s.connect((dest_ip, 8080)) s.sendall(b'...') print(s.recv(4096)) ``` - This assumes the proxy is running on port 4760 of localhost - This program is using SOCKS to connect to the dest_ip on port 8080 - SOCKS will handle the port forwarding ## SOCKS (Socket Secure) [![](https://upload.wikimedia.org/wikipedia/commons/f/fd/Villased_sokid%2C_STM_1998.jpg)](https://commons.wikimedia.org/wiki/File:Villased_sokid,_STM_1998.jpg) - The proxy was running on port 4760 of localhost - This is likely through some type of tunnel, perhaps an SSH port forward - The Python program picked the destination IP and port to connect to - The SOCKS proxy handled redirecting that one port through the tunnel and to it's final destination ## VPNs versus SOCKS proxies - VPNs are transparent to applications, SOCKS proxies are not - Setting up a VPN is more complicated - Any application can use a VPN; only the program that knows how to use SOCKS can use the proxy - VPN always encrypts your traffic - SOCKS proxies *may* encrypt your traffic -- it depends on what the tunnel is ## Other tunneling methods [![](https://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/Tunnels_Beaches_-_The_main_tunnel_-_geograph.org.uk_-_4149495.jpg/1024px-Tunnels_Beaches_-_The_main_tunnel_-_geograph.org.uk_-_4149495.jpg)](https://commons.wikimedia.org/wiki/File:Tunnels_Beaches_-_The_main_tunnel_-_geograph.org.uk_-_4149495.jpg) - ICMP: like in the [Ping Shell Commands](../hws/pingcmd/index.html) - We could send network data (packets) in the payload rather than shell commands and responses - HTTPS: all firewalls allow this traffic through - You need a program or plugin to route everything via HTTPS - And a receiving server