Moving on git

master
Meliurwen 4 years ago
commit 311afb19ce
Signed by: meliurwen
GPG Key ID: 818A8B35E9F1CE10
  1. 25
      .env.example
  2. 1
      .gitignore
  3. 22
      Dockerfile
  4. 28
      bin/add-openvpn-ipv4-dns-rules
  5. 5
      bin/add-openvpn-ipv4-rules
  6. 4
      bin/add-openvpn-ipv6-rules
  7. 4
      bin/enable_tun
  8. 214
      bin/openvpn-initialize
  9. 212
      bin/openvpn-menu
  10. 75
      bin/start.sh
  11. 75
      docker-compose.yml

@ -0,0 +1,25 @@
# Global Settings
TZ=Europe/Berlin
LOCAL_STACK_DIR=/srv/docker/volumes/openvpn
# OpenVPN General Settings
PUBLIC_IP=0.0.0.0
# OpenVPN - General
OGEN_PORT=1194
OGEN_PROTOCOL=udp
OGEN_IPV6=n
OGEN_DNS_ONLY=n
OGEN_DNS1=pihole
# OpenVPN - DNS
ODNS_PORT=1195
ODNS_PROTOCOL=udp
ODNS_IPV6=n
ODNS_DNS_ONLY=y
ODNS_DNS1=pihole
# Pi-Hole Settings
PHOLE_DNS1=1.1.1.1
PHOLE_DNS2=1.0.0.1
PHOLE_WEBPASSWORD=passwordhere

1
.gitignore vendored

@ -0,0 +1 @@
.env

@ -0,0 +1,22 @@
FROM debian:9
LABEL maintainer="Meliurwen <meliruwen@gmail.com>"
ADD ./bin /bin
RUN apt-get -q update && apt-get -qq install procps dnsutils \
ca-certificates gnupg openvpn iptables openssl wget ca-certificates curl && \
rm -rf /var/lib/apt/lists/* && \
chmod a+x /bin/* && \
mkdir -p /var/log/openvpn && \
apt-get autoremove --purge && \
apt-get clean
VOLUME ["/etc/openvpn"]
VOLUME ["/root"]
EXPOSE 1195/udp
WORKDIR /etc/openvpn
ENTRYPOINT ["start.sh"]

@ -0,0 +1,28 @@
#Set default policy of chain
iptables -P FORWARD DROP
#iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o 172.25.0.0/24 -j MASQUERADE
# Allow traffic initiated from VPN to access LAN
#iptables -I FORWARD -i tun0 -o $NIC -s 10.8.0.0/24 -d 172.25.0.0/24 -m conntrack --ctstate NEW -j ACCEPT
# Allow established traffic to pass back and forth
#iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -d $DNS1/32 -o $NIC -j MASQUERADE
#iptables -A INPUT -i tun0 -j ACCEPT
#iptables -A FORWARD -i $NIC -o tun0 -j ACCEPT
#iptables -A FORWARD -i tun0 -o $NIC -j ACCEPT
#iptables -A INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT
#iptables -A FORWARD -i tun0 -o $NIC -s 10.8.0.0/24 -d 172.25.0.0/24 -j ACCEPT
#iptables -A FORWARD -i $NIC -o tun0 -s $DNS1/32 -d 10.8.0.0/24 -j ACCEPT
#iptables -P FORWARD DROP
#allow traffic to route from VPN subnet to specific host in subnet
iptables -A FORWARD -i tun0 -s 10.8.0.0/24 -d $DNS1/32 -j ACCEPT
#allow traffic from host in server subnet back to VPN subnet
iptables -A FORWARD -o tun0 -s $DNS1/32 -d 10.8.0.0/24 -j ACCEPT

@ -0,0 +1,5 @@
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o $NIC -j MASQUERADE
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A FORWARD -i $NIC -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o $NIC -j ACCEPT
iptables -A INPUT -i $NIC -p $PROTOCOL --dport $PORT -j ACCEPT

@ -0,0 +1,4 @@
ip6tables -t nat -A POSTROUTING -s fd42:42:42:42::/112 -o $NIC -j MASQUERADE
ip6tables -A INPUT -i tun0 -j ACCEPT
ip6tables -A FORWARD -i $NIC -o tun0 -j ACCEPT
ip6tables -A FORWARD -i tun0 -o $NIC -j ACCEPT

@ -0,0 +1,4 @@
mkdir -p /dev/net
if [ ! -e /dev/net/tun ]; then
mknod /dev/net/tun c 10 200
fi

@ -0,0 +1,214 @@
#!/bin/bash
# Secure OpenVPN server installer for Debian, Ubuntu, CentOS, Fedora and Arch Linux
# https://github.com/angristan/openvpn-install
isRoot () {
if [ "$EUID" -ne 0 ]; then
return 1
fi
}
tunAvailable () {
if [ ! -e /dev/net/tun ]; then
return 1
fi
}
initialCheck () {
if ! isRoot; then
echo "Sorry, you need to run this as root"
exit 1
fi
if ! tunAvailable; then
echo "TUN is not available"
exit 1
fi
}
installQuestions () {
if [ -z "$IPV6_SUPPORT" ]; then
IPV6_SUPPORT=n
fi
if [ -z "$PORT" ]; then
PORT=1194
fi
if [ -z "$PROTOCOL" ]; then
PROTOCOL=udp
fi
if [ -z "$DNS1" ]; then
DNS1='1.1.1.1'
fi
CIPHER="AES-128-GCM"
CERT_CURVE="prime256v1"
CC_CIPHER="TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256"
DH_CURVE="prime256v1"
HMAC_ALG="SHA256"
}
initializeOpenVPN () {
# Run setup questions first
installQuestions
# Get the "public" interface from the default route
NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
# Find out if the machine uses nogroup or nobody for the permissionless group
if grep -qs "^nogroup:" /etc/group; then
NOGROUP=nogroup
else
NOGROUP=nobody
fi
# An old version of easy-rsa was available by default in some openvpn packages
if [[ -d /etc/openvpn/easy-rsa/ ]]; then
rm -rf /etc/openvpn/easy-rsa/
fi
# Install the latest version of easy-rsa from source
local version="3.0.6"
wget -O ~/EasyRSA-unix-v${version}.tgz https://github.com/OpenVPN/easy-rsa/releases/download/v${version}/EasyRSA-unix-v${version}.tgz
tar xzf ~/EasyRSA-unix-v${version}.tgz -C ~/
mv ~/EasyRSA-v${version}/ /etc/openvpn/
mv /etc/openvpn/EasyRSA-v${version}/ /etc/openvpn/easy-rsa/
chown -R root:root /etc/openvpn/easy-rsa/
rm -f ~/EasyRSA-unix-v${version}.tgz
cd /etc/openvpn/easy-rsa/
echo "set_var EASYRSA_ALGO ec" > vars
echo "set_var EASYRSA_CURVE $CERT_CURVE" >> vars
# Generate a random, alphanumeric identifier of 16 characters for CN and one for server name
SERVER_CN="cn_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
SERVER_NAME="server_$(head /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"
echo "set_var EASYRSA_REQ_CN $SERVER_CN" >> vars
# Create the PKI, set up the CA, the DH params and the server certificate
./easyrsa init-pki
./easyrsa --batch build-ca nopass
./easyrsa build-server-full "$SERVER_NAME" nopass
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
openvpn --genkey --secret /etc/openvpn/tls-crypt.key
# Move all the generated files
cp pki/ca.crt pki/private/ca.key "pki/issued/$SERVER_NAME.crt" "pki/private/$SERVER_NAME.key" /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn
# Generate server.conf
echo "port $PORT" > /etc/openvpn/server.conf
if [[ "$IPV6_SUPPORT" = 'n' ]]; then
echo "proto $PROTOCOL" >> /etc/openvpn/server.conf
elif [[ "$IPV6_SUPPORT" = 'y' ]]; then
echo "proto ${PROTOCOL}6" >> /etc/openvpn/server.conf
fi
echo "dev tun
user nobody
group $NOGROUP
persist-key
persist-tun
keepalive 10 120
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt" >> /etc/openvpn/server.conf
# DNS resolvers
echo 'push "dhcp-option DNS '${DNS1}'"' >> /etc/openvpn/server.conf
if [[ "$DNS_ONLY" = 'y' ]]; then
echo '#push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server.conf
else
echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server.conf
fi
# IPv6 network settings if needed
if [[ "$IPV6_SUPPORT" = 'y' ]]; then
echo 'server-ipv6 fd42:42:42:42::/112
tun-ipv6
push tun-ipv6
push "route-ipv6 2000::/3"
push "redirect-gateway ipv6"' >> /etc/openvpn/server.conf
fi
echo "dh none" >> /etc/openvpn/server.conf
echo "ecdh-curve $DH_CURVE" >> /etc/openvpn/server.conf
echo "tls-crypt tls-crypt.key 0" >> /etc/openvpn/server.conf
echo "crl-verify crl.pem
ca ca.crt
cert $SERVER_NAME.crt
key $SERVER_NAME.key
auth $HMAC_ALG
cipher $CIPHER
ncp-ciphers $CIPHER
tls-server
tls-version-min 1.2
tls-cipher $CC_CIPHER
status /var/log/openvpn/status.log
verb 3" >> /etc/openvpn/server.conf
# Enable routing
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/20-openvpn.conf
if [[ "$IPV6_SUPPORT" = 'y' ]]; then
echo 'net.ipv6.conf.all.forwarding=1' >> /etc/sysctl.d/20-openvpn.conf
fi
# Avoid an unneeded reboot
sysctl --system
# If SELinux is enabled and a custom port was selected, we need this
if hash sestatus 2>/dev/null; then
if sestatus | grep "Current mode" | grep -qs "enforcing"; then
if [[ "$PORT" != '1194' ]]; then
semanage port -a -t openvpn_port_t -p "$PROTOCOL" "$PORT"
fi
fi
fi
IP=$PUBLICIP
# client-template.txt is created so we have a template to add further users later
echo "client" > /etc/openvpn/client-template.txt
if [[ "$PROTOCOL" = 'udp' ]]; then
echo "proto udp" >> /etc/openvpn/client-template.txt
elif [[ "$PROTOCOL" = 'tcp' ]]; then
echo "proto tcp-client" >> /etc/openvpn/client-template.txt
fi
echo "remote $IP $PORT
dev tun
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
verify-x509-name $SERVER_NAME name
auth $HMAC_ALG
auth-nocache
cipher $CIPHER
tls-client
tls-version-min 1.2
tls-cipher $CC_CIPHER
setenv opt block-outside-dns # Prevent Windows 10 DNS leak
verb 3" >> /etc/openvpn/client-template.txt
}
# Check for root, TUN, OS...
initialCheck
initializeOpenVPN

@ -0,0 +1,212 @@
#!/bin/bash
# Secure OpenVPN server installer for Debian, Ubuntu, CentOS, Fedora and Arch Linux
# https://github.com/angristan/openvpn-install
function isRoot () {
if [ "$EUID" -ne 0 ]; then
return 1
fi
}
function tunAvailable () {
if [ ! -e /dev/net/tun ]; then
return 1
fi
}
function checkOS () {
if [[ -e /etc/debian_version ]]; then
OS="debian"
source /etc/os-release
if [[ "$ID" == "debian" ]]; then
if [[ ! $VERSION_ID =~ (8|9) ]]; then
echo "⚠ Your version of Debian is not supported."
echo ""
echo "However, if you're using Debian >= 9 or unstable/testing then you can continue."
echo "Keep in mind they are not supported, though."
echo ""
until [[ $CONTINUE =~ (y|n) ]]; do
read -rp "Continue? [y/n]: " -e CONTINUE
done
if [[ "$CONTINUE" = "n" ]]; then
exit 1
fi
fi
fi
else
echo "Looks like you aren't running this installer on a Debian Linux system"
exit 1
fi
}
function initialCheck () {
if ! isRoot; then
echo "Sorry, you need to run this as root"
exit 1
fi
if ! tunAvailable; then
echo "TUN is not available"
exit 1
fi
checkOS
}
function newClient () {
echo ""
echo "Tell me a name for the client."
echo "Use one word only, no special characters."
until [[ "$CLIENT" =~ ^[a-zA-Z0-9_]+$ ]]; do
read -rp "Client name: " -e CLIENT
done
echo ""
echo "Do you want to protect the configuration file with a password?"
echo "(e.g. encrypt the private key with a password)"
echo " 1) Add a passwordless client"
echo " 2) Use a password for the client"
until [[ "$PASS" =~ ^[1-2]$ ]]; do
read -rp "Select an option [1-2]: " -e -i 1 PASS
done
cd /etc/openvpn/easy-rsa/ || return
case $PASS in
1)
./easyrsa build-client-full "$CLIENT" nopass
;;
2)
echo "⚠ You will be asked for the client password below ⚠"
./easyrsa build-client-full "$CLIENT"
;;
esac
# Home directory of the user, where the client configuration (.ovpn) will be written
if [ -e "/home/$CLIENT" ]; then # if $1 is a user name
homeDir="/home/$CLIENT"
elif [ "${SUDO_USER}" ]; then # if not, use SUDO_USER
homeDir="/home/${SUDO_USER}"
else # if not SUDO_USER, use /root
homeDir="/root"
fi
# Determine if we use tls-auth or tls-crypt
if grep -qs "^tls-crypt" /etc/openvpn/server.conf; then
TLS_SIG="1"
elif grep -qs "^tls-auth" /etc/openvpn/server.conf; then
TLS_SIG="2"
fi
# Generates the custom client.ovpn
cp /etc/openvpn/client-template.txt "$homeDir/$CLIENT.ovpn"
{
echo "<ca>"
cat "/etc/openvpn/easy-rsa/pki/ca.crt"
echo "</ca>"
echo "<cert>"
awk '/BEGIN/,/END/' "/etc/openvpn/easy-rsa/pki/issued/$CLIENT.crt"
echo "</cert>"
echo "<key>"
cat "/etc/openvpn/easy-rsa/pki/private/$CLIENT.key"
echo "</key>"
case $TLS_SIG in
1)
echo "<tls-crypt>"
cat /etc/openvpn/tls-crypt.key
echo "</tls-crypt>"
;;
2)
echo "key-direction 1"
echo "<tls-auth>"
cat /etc/openvpn/tls-auth.key
echo "</tls-auth>"
;;
esac
} >> "$homeDir/$CLIENT.ovpn"
echo ""
echo "Client $CLIENT added, the configuration file is available at $homeDir/$CLIENT.ovpn."
echo "Download the .ovpn file and import it in your OpenVPN client."
}
function revokeClient () {
NUMBEROFCLIENTS=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep -c "^V")
if [[ "$NUMBEROFCLIENTS" = '0' ]]; then
echo ""
echo "You have no existing clients!"
exit 1
fi
echo ""
echo "Select the existing client certificate you want to revoke"
tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | nl -s ') '
if [[ "$NUMBEROFCLIENTS" = '1' ]]; then
read -rp "Select one client [1]: " CLIENTNUMBER
else
read -rp "Select one client [1-$NUMBEROFCLIENTS]: " CLIENTNUMBER
fi
CLIENT=$(tail -n +2 /etc/openvpn/easy-rsa/pki/index.txt | grep "^V" | cut -d '=' -f 2 | sed -n "$CLIENTNUMBER"p)
cd /etc/openvpn/easy-rsa/
./easyrsa --batch revoke "$CLIENT"
EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
# Cleanup
rm -f "pki/reqs/$CLIENT.req"
rm -f "pki/private/$CLIENT.key"
rm -f "pki/issued/$CLIENT.crt"
rm -f /etc/openvpn/crl.pem
cp /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn/crl.pem
chmod 644 /etc/openvpn/crl.pem
find /home/ -maxdepth 2 -name "$CLIENT.ovpn" -delete
rm -f "/root/$CLIENT.ovpn"
sed -i "s|^$CLIENT,.*||" /etc/openvpn/ipp.txt
echo ""
echo "Certificate for client $CLIENT revoked."
}
function manageMenu () {
clear
echo "Welcome to OpenVPN-install!"
echo "The git repository is available at: https://github.com/angristan/openvpn-install"
echo ""
echo "It looks like OpenVPN is already installed."
echo ""
echo "What do you want to do?"
echo " 1) Add a new user"
echo " 2) Revoke existing user"
echo " 3) Exit"
until [[ "$MENU_OPTION" =~ ^[1-4]$ ]]; do
read -rp "Select an option [1-4]: " MENU_OPTION
done
case $MENU_OPTION in
1)
newClient
;;
2)
revokeClient
;;
3)
exit 0
;;
esac
}
# Check for root, TUN, OS...
initialCheck
# Check if OpenVPN is already installed
if [[ -e /etc/openvpn/server.conf ]]; then
manageMenu
else
echo 'No configuration file detected!'
fi

@ -0,0 +1,75 @@
#!/bin/bash
if [ -z "$PUBLICIP" ]; then
echo 'No PUBLICIP, exiting...'
exit 1
fi
mkdir -p /dev/net
if [ ! -e /dev/net/tun ]; then
mknod /dev/net/tun c 10 200
fi
if [ -z "$DNS_ONLY" ]; then
DNS_ONLY=n
fi
if [ ! -e /etc/openvpn/server.conf ]; then
echo "Configuration file not found. Initializing..."
openvpn-initialize
fi
OPENVPN_CONFIG_FILE=/etc/openvpn/server.conf
if [ -z $DNS1 ]; then
echo "DNS1 env variable not set, setting as deafault Cloudflare's 1.1.1.1"
$DNS1 = '1.1.1.1'
sed -i -e 's/"dhcp-option DNS .*"/"dhcp-option DNS '${DNS1}'"/g' ${OPENVPN_CONFIG_FILE}
else
if [[ $DNS1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "The DNS1 address is ${DNS1}"
sed -i -e 's/"dhcp-option DNS .*"/"dhcp-option DNS '${DNS1}'"/g' ${OPENVPN_CONFIG_FILE}
else
if echo "$DNS1" | grep -qP '^[a-z0-9](?!.*--)[a-z0-9-]{1,61}[a-z0-9]$' ; then
echo "DNS1 name of the container vaild"
DNS1=$(host pihole | grep -oE "\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b")
if [ ! -z $DNS1 ]; then
echo "The DNS1 container address is ${DNS1}"
sed -i -e 's/"dhcp-option DNS .*"/"dhcp-option DNS '${DNS1}'"/g' ${OPENVPN_CONFIG_FILE}
else
echo "Impossible to resolve the DNS1 container address, exiting..."
exit 1
fi
else
echo "DNS1 name of the container not vaild, please try to not use spaces or special characters, exiting..."
exit 1
fi
fi
fi
if [[ "$DNS_ONLY" = 'y' ]]; then
sed -i 's/#push "redirect-gateway def1 bypass-dhcp"/push "redirect-gateway def1 bypass-dhcp"/g' ${OPENVPN_CONFIG_FILE}
else
sed -i 's/push "redirect-gateway def1 bypass-dhcp"/push "redirect-gateway def1 bypass-dhcp"/g' ${OPENVPN_CONFIG_FILE}
fi
# Get the \"public\" interface from the default route
export NIC=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | head -1)
# Add iptable rules
if [[ "$DNS_ONLY" = 'y' ]]; then
add-openvpn-ipv4-dns-rules
else
add-openvpn-ipv4-rules
fi
if [ '$IPV6_SUPPORT' = 'y' ]; then
add-openvpn-ipv6-rules
fi
exec openvpn --config server.conf

@ -0,0 +1,75 @@
version: "3"
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
expose:
- "53/udp"
- "53/tcp"
- "80/tcp"
- "443/tcp"
volumes:
- '${LOCAL_STACK_DIR}/etc-pihole/:/etc/pihole/'
- '${LOCAL_STACK_DIR}/etc-dnsmasq.d/:/etc/dnsmasq.d/'
dns:
- 127.0.0.1
- ${PHOLE_DNS1}
restart: unless-stopped
networks:
- piholenetwork
environment:
TZ: ${TZ}
WEBPASSWORD: ${PHOLE_WEBPASSWORD}
DNS1: ${PHOLE_DNS1}
DNS2: ${PHOLE_DNS2}
openvpn-dns:
build: .
container_name: openvpn-dns
restart: unless-stopped
depends_on:
- pihole
volumes:
- ${LOCAL_STACK_DIR}/openvpn-dns/etc/openvpn:/etc/openvpn
- ${LOCAL_STACK_DIR}/openvpn-dns/root:/root
ports:
- "${ODNS_PORT}:${ODNS_PORT}/${ODNS_PROTOCOL}"
networks:
- piholenetwork
cap_add:
- NET_ADMIN
environment:
PUBLICIP: ${PUBLIC_IP}
PORT: ${ODNS_PORT}
PROTOCOL: ${ODNS_PROTOCOL}
IPV6_SUPPORT: ${ODNS_IPV6}
DNS_ONLY: ${ODNS_DNS_ONLY}
DNS1: ${ODNS_DNS1} # Add an IPv4 Address or a container name
openvpn-general:
build: .
container_name: openvpn-general
restart: unless-stopped
depends_on:
- pihole
volumes:
- ${LOCAL_STACK_DIR}/openvpn-general/etc/openvpn:/etc/openvpn
- ${LOCAL_STACK_DIR}/openvpn-general/root:/root
ports:
- "${OGEN_PORT}:${OGEN_PORT}/${OGEN_PROTOCOL}"
networks:
- piholenetwork
cap_add:
- NET_ADMIN
environment:
PUBLICIP: ${PUBLIC_IP}
PORT: ${OGEN_PORT}
PROTOCOL: ${OGEN_PROTOCOL}
IPV6_SUPPORT: ${OGEN_IPV6}
DNS_ONLY: ${OGEN_DNS_ONLY}
DNS1: ${OGEN_DNS1} # Add an IPv4 Address or a container name
networks:
piholenetwork:
driver: bridge
Loading…
Cancel
Save