From 5229459f99c5204f59697f880508f05cbb6d3999 Mon Sep 17 00:00:00 2001 From: Nyr Date: Wed, 1 Apr 2020 01:17:17 +0200 Subject: [PATCH] IPv6 support Clients will be provided with IPv6 connectivity if the server has it. Other very small and unimportant improvements are also included in this commit. --- openvpn-install.sh | 81 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 15 deletions(-) diff --git a/openvpn-install.sh b/openvpn-install.sh index 5134b2f..d3c3f00 100644 --- a/openvpn-install.sh +++ b/openvpn-install.sh @@ -159,7 +159,7 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then port=$(grep '^port ' /etc/openvpn/server/server.conf | cut -d " " -f 2) protocol=$(grep '^proto ' /etc/openvpn/server/server.conf | cut -d " " -f 2) if pgrep firewalld; then - ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24 -j SNAT --to ' | cut -d " " -f 10) + ip=$(firewall-cmd --direct --get-rules ipv4 nat POSTROUTING | grep '\-s 10.8.0.0/24 '"'"'!'"'"' -d 10.8.0.0/24' | grep -oE '[^ ]+$') # Using both permanent and not permanent rules to avoid a firewalld reload. firewall-cmd --remove-port="$port"/"$protocol" firewall-cmd --zone=trusted --remove-source=10.8.0.0/24 @@ -167,6 +167,13 @@ if [[ -e /etc/openvpn/server/server.conf ]]; then firewall-cmd --permanent --zone=trusted --remove-source=10.8.0.0/24 firewall-cmd --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" firewall-cmd --permanent --direct --remove-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" + if grep -qs "server-ipv6" /etc/openvpn/server/server.conf; then + ip6=$(firewall-cmd --direct --get-rules ipv6 nat POSTROUTING | grep '\-s fddd:1194:1194:1194::/64 '"'"'!'"'"' -d fddd:1194:1194:1194::/64' | grep -oE '[^ ]+$') + firewall-cmd --zone=trusted --remove-source=fddd:1194:1194:1194::/64 + firewall-cmd --permanent --zone=trusted --remove-source=fddd:1194:1194:1194::/64 + firewall-cmd --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6" + firewall-cmd --permanent --direct --remove-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6" + fi else systemctl disable --now openvpn-iptables.service rm -f /etc/systemd/system/openvpn-iptables.service @@ -201,22 +208,22 @@ else echo "I need to ask you a few questions before starting setup." echo "You can use the default options and just press enter if you are ok with them." # If system has a single IPv4, it is selected automatically. Else, ask the user - if [[ $(ip addr | grep inet | grep -v inet6 | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') -eq 1 ]]; then - ip=$(ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + if [[ $(ip -4 addr | grep inet | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') -eq 1 ]]; then + ip=$(ip -4 addr | grep inet | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') else - number_of_ips=$(ip addr | grep inet | grep -v inet6 | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') + number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}') echo - echo "What IPv4 address should the OpenVPN server bind to?" - ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | nl -s ') ' + echo "What IPv4 address should the OpenVPN server use?" + ip -4 addr | grep inet | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | nl -s ') ' read -p "IPv4 address [1]: " ip_number - until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ips" ]]; do + until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do echo "$ip_number: invalid selection." read -p "IPv4 address [1]: " ip_number done [[ -z "$ip_number" ]] && ip_number="1" - ip=$(ip addr | grep inet | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed -n "$ip_number"p) + ip=$(ip -4 addr | grep inet | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed -n "$ip_number"p) fi - # If $IP is a private IP address, the server must be behind NAT + # If $ip is a private IP address, the server must be behind NAT if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then echo echo "This server is behind NAT. What is the public IPv4 address or hostname?" @@ -224,6 +231,24 @@ else read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip [ -z "$public_ip" ] && public_ip="$get_public_ip" fi + # If system has a single IPv6, it is selected automatically + if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then + ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}') + fi + # If system has multiple IPv6, ask the user to select one + if [[ $(ip -6 addr | grep -c 'inet6 [23]') -gt 1 ]]; then + number_of_ip6=$(ip -6 addr | grep -c 'inet6 [23]') + echo + echo "What IPv6 address should the OpenVPN server use?" + ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | nl -s ') ' + read -p "IPv6 address [1]: " ip6_number + until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do + echo "$ip6_number: invalid selection." + read -p "IPv6 address [1]: " ip6_number + done + [[ -z "$ip6_number" ]] && ip6_number="1" + ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | sed -n "$ip6_number"p) + fi echo echo "Which protocol do you want for OpenVPN connections?" echo " 1) UDP (recommended)" @@ -326,9 +351,15 @@ dh dh.pem auth SHA512 tls-crypt tc.key topology subnet -server 10.8.0.0 255.255.255.0 -ifconfig-pool-persist ipp.txt" > /etc/openvpn/server/server.conf - echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf +server 10.8.0.0 255.255.255.0" > /etc/openvpn/server/server.conf + # IPv6 + if [[ -z "$ip6" ]]; then + echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server/server.conf + else + echo 'server-ipv6 fddd:1194:1194:1194::/64' >> /etc/openvpn/server/server.conf + echo 'push "redirect-gateway def1 ipv6 bypass-dhcp"' >> /etc/openvpn/server/server.conf + fi + echo 'ifconfig-pool-persist ipp.txt' >> /etc/openvpn/server/server.conf # DNS case "$dns" in 1|"") @@ -377,6 +408,12 @@ crl-verify crl.pem" >> /etc/openvpn/server/server.conf echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/30-openvpn-forward.conf # Enable without waiting for a reboot or service restart echo 1 > /proc/sys/net/ipv4/ip_forward + if [[ -n "$ip6" ]]; then + # Enable net.ipv6.conf.all.forwarding for the system + echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.d/30-openvpn-forward.conf + # Enable without waiting for a reboot or service restart + echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + fi if pgrep firewalld; then # Using both permanent and not permanent rules to avoid a firewalld # reload. @@ -389,6 +426,12 @@ crl-verify crl.pem" >> /etc/openvpn/server/server.conf # Set NAT for the VPN subnet firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to "$ip" + if [[ -n "$ip6" ]]; then + firewall-cmd --zone=trusted --add-source=fddd:1194:1194:1194::/64 + firewall-cmd --permanent --zone=trusted --add-source=fddd:1194:1194:1194::/64 + firewall-cmd --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6" + firewall-cmd --permanent --direct --add-rule ipv6 nat POSTROUTING 0 -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to "$ip6" + fi else # Create a service to set up persistent iptables rules echo "[Unit] @@ -402,10 +445,18 @@ ExecStart=/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCE ExecStop=/sbin/iptables -t nat -D POSTROUTING -s 10.8.0.0/24 ! -d 10.8.0.0/24 -j SNAT --to $ip ExecStop=/sbin/iptables -D INPUT -p $protocol --dport $port -j ACCEPT ExecStop=/sbin/iptables -D FORWARD -s 10.8.0.0/24 -j ACCEPT -ExecStop=/sbin/iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT -RemainAfterExit=yes +ExecStop=/sbin/iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" > /etc/systemd/system/openvpn-iptables.service + if [[ -n "$ip6" ]]; then + echo "ExecStart=/sbin/ip6tables -t nat -A POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6 +ExecStart=/sbin/ip6tables -I FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT +ExecStart=/sbin/ip6tables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT +ExecStop=/sbin/ip6tables -t nat -D POSTROUTING -s fddd:1194:1194:1194::/64 ! -d fddd:1194:1194:1194::/64 -j SNAT --to $ip6 +ExecStop=/sbin/ip6tables -D FORWARD -s fddd:1194:1194:1194::/64 -j ACCEPT +ExecStop=/sbin/ip6tables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" >> /etc/systemd/system/openvpn-iptables.service + fi + echo "RemainAfterExit=yes [Install] -WantedBy=multi-user.target" > /etc/systemd/system/openvpn-iptables.service +WantedBy=multi-user.target" >> /etc/systemd/system/openvpn-iptables.service systemctl enable --now openvpn-iptables.service fi # If SELinux is enabled and a custom port was selected, we need this