-
Notifications
You must be signed in to change notification settings - Fork 118
/
openvpn.sh
280 lines (233 loc) · 8.27 KB
/
openvpn.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#!/bin/bash
# defaults
ADMINPASSWORD="secret"
DNS1="8.8.8.8"
DNS2="8.8.4.4"
PROTOCOL=udp
EMAIL=""
PORT=1194
HOST=$(wget -4qO- "http://whatismyip.akamai.com/")
VERSION="3.0.1"
for i in "$@"
do
case $i in
--adminpassword=*)
ADMINPASSWORD="${i#*=}"
;;
--dns1=*)
DNS1="${i#*=}"
;;
--dns2=*)
DNS2="${i#*=}"
;;
--vpnport=*)
PORT="${i#*=}"
;;
--protocol=*)
PROTOCOL="${i#*=}"
;;
--host=*)
HOST="${i#*=}"
;;
--email=*)
EMAIL="${i#*=}"
;;
*)
;;
esac
done
[ "${ADMINPASSWORD}" == "secret" ] && echo "fatal: password is not set" && exit 1
[ "${EMAIL}" == "" ] && echo "fatal: email is not set" && exit 1
# Detect Debian users running the script with "sh" instead of bash
if readlink /proc/$$/exe | grep -qs "dash"; then
echo "This script needs to be run with bash, not sh"
exit 1
fi
if [[ "$EUID" -ne 0 ]]; then
echo "Sorry, you need to run this as root"
exit 2
fi
if [[ ! -e /dev/net/tun ]]; then
echo "The TUN device is not available. You need to enable TUN before running this script."
exit 3
fi
if [[ -e /etc/debian_version ]]; then
OS=debian
GROUPNAME=nogroup
RCLOCAL='/etc/rc.local'
else
echo "Looks like you aren't running this installer on Debian or Ubuntu"
exit 5
fi
# Try to get our IP from the system and fallback to the Internet.
IP=$(ip addr | grep 'inet' | grep -v inet6 | grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1)
if [[ "$IP" = "" ]]; then
IP=$(wget -4qO- "http://whatismyip.akamai.com/")
fi
apt-get update
apt-get install openvpn iptables openssl fcgiwrap ca-certificates certbot python3-certbot-nginx apache2-utils nginx -y
# 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
# Get easy-rsa
wget -O ~/EasyRSA-${VERSION}.tgz "https://github.com/OpenVPN/easy-rsa/releases/download/3.0.1/EasyRSA-${VERSION}.tgz"
tar xzf ~/EasyRSA-${VERSION}.tgz -C ~/
mv ~/EasyRSA-${VERSION}/ /etc/openvpn/
mv /etc/openvpn/EasyRSA-${VERSION}/ /etc/openvpn/easy-rsa/
chown -R root:root /etc/openvpn/easy-rsa/
rm -f ~/EasyRSA-${VERSION}.tgz
cd /etc/openvpn/easy-rsa/
# Create the PKI, set up the CA, the DH params and the server + client certificates
./easyrsa init-pki
./easyrsa --batch build-ca nopass
./easyrsa gen-dh
./easyrsa build-server-full server nopass
# ./easyrsa build-client-full $CLIENT nopass
./easyrsa gen-crl
# Move the stuff we need
cp pki/ca.crt pki/private/ca.key pki/dh.pem pki/issued/server.crt pki/private/server.key /etc/openvpn/easy-rsa/pki/crl.pem /etc/openvpn
# CRL is read with each client connection, when OpenVPN is dropped to nobody
chown nobody:$GROUPNAME /etc/openvpn/crl.pem
# Generate key for tls-auth
openvpn --genkey --secret /etc/openvpn/ta.key
# Generate server.conf
echo "port $PORT
proto $PROTOCOL
dev tun
sndbuf 0
rcvbuf 0
ca ca.crt
cert server.crt
key server.key
dh dh.pem
tls-auth ta.key 0
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt" > /etc/openvpn/server.conf
echo 'push "redirect-gateway def1 bypass-dhcp"' >> /etc/openvpn/server.conf
# DNS
echo "push \"dhcp-option DNS $DNS1\"" >> /etc/openvpn/server.conf
echo "push \"dhcp-option DNS $DNS2\"" >> /etc/openvpn/server.conf
echo "keepalive 10 120
cipher AES-256-CBC
user nobody
group $GROUPNAME
persist-key
persist-tun
status openvpn-status.log
verb 3
crl-verify crl.pem" >> /etc/openvpn/server.conf
# Enable net.ipv4.ip_forward for the system
sed -i '/\<net.ipv4.ip_forward\>/c\net.ipv4.ip_forward=1' /etc/sysctl.conf
if ! grep -q "\<net.ipv4.ip_forward\>" /etc/sysctl.conf; then
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
fi
# Avoid an unneeded reboot
echo 1 > /proc/sys/net/ipv4/ip_forward
if pgrep firewalld; then
# Using both permanent and not permanent rules to avoid a firewalld
# reload.
# We don't use --add-service=openvpn because that would only work with
# the default port and protocol.
firewall-cmd --zone=public --add-port=$PORT/$PROTOCOL
firewall-cmd --zone=trusted --add-source=10.8.0.0/24
firewall-cmd --permanent --zone=public --add-port=$PORT/$PROTOCOL
firewall-cmd --permanent --zone=trusted --add-source=10.8.0.0/24
# Set NAT for the VPN subnet
firewall-cmd --direct --add-rule ipv4 nat POSTROUTING 0 -s 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 -j SNAT --to $IP
else
# Needed to use rc.local with some systemd distros
if [[ "$OS" = 'debian' && ! -e $RCLOCAL ]]; then
echo '#!/bin/sh -e
exit 0' > $RCLOCAL
fi
chmod +x $RCLOCAL
# Set NAT for the VPN subnet
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT --to $IP
sed -i "1 a\iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j SNAT --to $IP" $RCLOCAL
if iptables -L -n | grep -qE '^(REJECT|DROP)'; then
# If iptables has at least one REJECT rule, we asume this is needed.
# Not the best approach but I can't think of other and this shouldn't
# cause problems.
iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT
iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT
iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
sed -i "1 a\iptables -I INPUT -p $PROTOCOL --dport $PORT -j ACCEPT" $RCLOCAL
sed -i "1 a\iptables -I FORWARD -s 10.8.0.0/24 -j ACCEPT" $RCLOCAL
sed -i "1 a\iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT" $RCLOCAL
fi
fi
# If SELinux is enabled and a custom port or TCP was selected, we need this
if hash sestatus 2>/dev/null; then
if sestatus | grep "Current mode" | grep -qs "enforcing"; then
if [[ "$PORT" != '1194' || "$PROTOCOL" = 'tcp' ]]; then
# semanage isn't available in CentOS 6 by default
if ! hash semanage 2>/dev/null; then
yum install policycoreutils-python -y
fi
semanage port -a -t openvpn_port_t -p $PROTOCOL $PORT
fi
fi
fi
# And finally, restart OpenVPN
# Little hack to check for systemd
if pgrep systemd-journal; then
systemctl restart [email protected]
else
/etc/init.d/openvpn restart
fi
# Try to detect a NATed connection and ask about it to potential LowEndSpirit users
# client-common.txt is created so we have a template to add further users later
echo "client
dev tun
proto $PROTOCOL
sndbuf 0
rcvbuf 0
remote $HOST $PORT
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
setenv opt block-outside-dns
key-direction 1
verb 3" > /etc/openvpn/client-common.txt
# Generates the custom client.ovpn
mv /etc/openvpn/clients/ /etc/openvpn/clients.$$/
mkdir /etc/openvpn/clients/
#Setup the web server to use an self signed cert
# mkdir /etc/openvpn/clients/
#Set permissions for easy-rsa and open vpn to be modified by the web user.
chown -R www-data:www-data /etc/openvpn/easy-rsa
chown -R www-data:www-data /etc/openvpn/clients/
chmod -R 755 /etc/openvpn/
chmod -R 777 /etc/openvpn/crl.pem
chmod g+s /etc/openvpn/clients/
chmod g+s /etc/openvpn/easy-rsa/
#Generate a self-signed certificate for the web server
# mv /etc4/lighttpd/ssl/ /etc/lighttpd/ssl.$$/
# mkdir /etc/nginx/ssl/
# openssl req -x509 -nodes -days 9999 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt -subj "/C=US/ST=California/L=San Francisco/O=example.com/OU=Ops Department/CN=example.com"
#Configure the web server with the lighttpd.conf from GitHub
mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.$$
wget -O /etc/nginx/sites-available/default https://raw.githubusercontent.com/theonemule/simple-openvpn-server/master/default
sed -i "s/^[[:space:]]*server_name[[:space:]]*example.com;$/\tserver_name\t$HOST;/g" /etc/nginx/sites-available/default
#install the webserver scripts
rm /var/www/html/*
mkdir -p /var/www/html/
wget -O /var/www/html/index.sh https://raw.githubusercontent.com/theonemule/simple-openvpn-server/master/index.sh
wget -O /var/www/html/download.sh https://raw.githubusercontent.com/theonemule/simple-openvpn-server/master/download.sh
chown -R www-data:www-data /var/www/html/
chmod +x /var/www/html/download.sh
chmod +x /var/www/html/index.sh
#set the password file for the WWW logon
# systecho "admin:$ADMINPASSWORD" >> /etc/lighttpd/.lighttpdpassword
htpasswd -b -c /etc/nginx/.htpasswd admin $ADMINPASSWORD
#Obtain a Certificate from Let's Encrypt
certbot run -d $HOST --agree-tos --nginx -m $EMAIL -n
systemctl restart apache2
#restart the web server
systemctl restart nginx