#!/bin/bash

#Black        0;30     Dark Gray     1;30
#Red          0;31     Light Red     1;31
#Green        0;32     Light Green   1;32
#Brown/Orange 0;33     Yellow        1;33
#Blue         0;34     Light Blue    1;34
#Purple       0;35     Light Purple  1;35
#Cyan         0;36     Light Cyan    1;36
#Light Gray   0;37     White         1;37

HL='\033[1;33m'
RED='\033[0;31m'
WHITE='\033[1;36m'
NC='\033[0m' # No Color

printf "${WHITE}PIA VPN Firewall v0.31${NC}\n\n"

if [ "$(id -u)" != "0" ]; then
   printf "${RED}FATAL ERROR:${NC} This script must be run as root (sudo)!\n"
   exit 1
fi

IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
printf "${HL}YOUR IP:${NC} $IP\n"

printf "${HL}ACTIVATING FIREWALL...\nNOTE:${NC} vpn should be connected here!\n"

## GET ALL VPN SERVERS IP ADDRESSES
servers=$(curl -Ss "https://www.privateinternetaccess.com/vpninfo/servers?version=24" | head -1)
VPN_SERVERS=$(python3 - <<END
import re
import os
ip = re.findall( r'[0-9]+(?:\.[0-9]+){3}', '$servers' )
u_ip = list(set(ip))
for i in u_ip:
	print(i, end=" ")
END
)

printf "${HL}AVAILABLE VPN SERVERS:${NC}\n"
for VPN in $VPN_SERVERS; do
	printf $VPN' '
done
printf "\n"

VPN_INTERFACE=$(ifconfig | grep tun | head -c 4)
LOCAL_NET="192.168.0.0/16 127.0.0.0/8"

printf "${HL}VPN INTERFACE:${NC} $VPN_INTERFACE\n"
printf "${HL}LOCAL NETWORKS:${NC} $LOCAL_NET\n"

###########################
## IPv4 DEFAULTS
###########################

## Set secure defaults.
iptables -P INPUT DROP

## FORWARD rules does not actually do anything if forwarding is disabled. Better be safe just in case.
iptables -P FORWARD DROP

## Only the VPN process is allowed to establish outgoing connections.
iptables -P OUTPUT DROP

###########################
## IPv4 PREPARATIONS
###########################

## Flush old rules.
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

############################
## IPv4 DROP INVALID PACKAGES
############################

## DROP INVALID
iptables -A INPUT -m state --state INVALID -j DROP

## DROP INVALID SYN PACKETS
iptables -A INPUT -p tcp --tcp-flags ALL ACK,RST,SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP

## DROP PACKETS WITH INCOMING FRAGMENTS. THIS ATTACK ONCE RESULTED IN KERNEL PANICS
iptables -A INPUT -f -j DROP

## DROP INCOMING MALFORMED XMAS PACKETS
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

## DROP INCOMING MALFORMED NULL PACKETS
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

###########################
## IPv4 INPUT
###########################

## Traffic on the loopback interface is accepted.
iptables -A INPUT -i lo -j ACCEPT

## Established incoming connections are accepted.
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

## Allow all incoming connections on the virtual VPN network interface.
iptables -A INPUT -i "$VPN_INTERFACE" -j ACCEPT

# torrents socks5
#iptables -A INPUT -p udp -m udp -s 109.201.138.230 --dport 1080 -j ACCEPT

## Log.
iptables -A INPUT -j LOG --log-prefix "VPN firewall blocked input4: "

## Reject anything not explicitly allowed above.
## Drop is better than reject here, because ...
iptables -A INPUT -j DROP

###########################
## IPv4 FORWARD
###########################

## Log.
iptables -A FORWARD -j LOG --log-prefix "VPN firewall blocked forward4: "

## Reject everything.
iptables -A FORWARD -j REJECT --reject-with icmp-admin-prohibited

###########################
## IPv4 OUTPUT
###########################

## XXX
iptables -A OUTPUT -o "$VPN_INTERFACE" -j ACCEPT

## XXX
for SERVER in $VPN_SERVERS; do
  iptables -A OUTPUT -d "$SERVER" -j ACCEPT
done

## Accept outgoing connections to local network.
for NET in $LOCAL_NET; do
   iptables -A OUTPUT -d "$NET" -j ACCEPT
done

# torrents socks5
#iptables -A OUTPUT -p udp -m udp -d 109.201.138.230 --sport 1080 -j ACCEPT

## Existing connections are accepted.
#iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED,INVALID -j ACCEPT

## Log.
iptables -A OUTPUT -j LOG --log-prefix "VPN firewall blocked output4: "

## Reject all other outgoing traffic.
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited

###########################
## IPv6
###########################

## Policy DROP for all traffic as fallback.
ip6tables -P INPUT DROP
ip6tables -P OUTPUT DROP
ip6tables -P FORWARD DROP

## Flush old rules.
ip6tables -F
ip6tables -X
ip6tables -t mangle -F
ip6tables -t mangle -X

## Allow unlimited access on loopback.
#ip6tables -A INPUT -i lo -j ACCEPT
#ip6tables -A OUTPUT -o lo -j ACCEPT

## Log.
ip6tables -A INPUT -j LOG --log-prefix "VPN firewall blocked input6: "
ip6tables -A OUTPUT -j LOG --log-prefix "VPN firewall blocked output6: "
ip6tables -A FORWARD -j LOG --log-prefix "VPN firewall blocked forward6: "

## Drop/reject all other traffic.
ip6tables -A INPUT -j DROP
## --reject-with icmp-admin-prohibited not supported by ip6tables
ip6tables -A OUTPUT -j REJECT
## --reject-with icmp-admin-prohibited not supported by ip6tables
ip6tables -A FORWARD -j REJECT

###########################
## End
###########################

printf "${HL}LOADING NEW IPTABLES...${NC}\n"
iptables -L		# bug happening here

printf "${HL}CHECKING PING...${NC}\n"
ping -c 5 8.8.8.8
if [ $(printf "$?") = 0 ]; then
	printf "${HL}FIREWALL CONFIGURATION ${WHITE}COMPLITED${NC}\n"
else
	printf "${HL}FIREWALL CONFIGURATION ${RED}FAILED${NC}\n"
	exit 1
fi

exit 0





