Overview
Comment: | add vpn tool |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
75223838e1bae48168201470b2857ed2 |
User & Date: | lexi on 2019-05-03 15:21:43 |
Other Links: | manifest | tags |
Context
2019-05-04
| ||
02:38 | updates check-in: 05feae3cd3 user: lexi tags: trunk | |
2019-05-03
| ||
15:21 | add vpn tool check-in: 75223838e1 user: lexi tags: trunk | |
2019-05-01
| ||
01:03 | refactor tenki check-in: 70991b55c3 user: lexi tags: trunk | |
Changes
Added vpn/conf version [d086ba0334].
1 +# [ʞ] vpn/conf 2 +# ~ lexi hale <lexi@hale.su> 3 +# © public domain / CC0 4 + 5 +# this is the master configuration file for 6 +# openvpn used by the `vpn` utility. these should 7 +# be sane-enough defaults for almost all cases. 8 +# server-specific config should be placed in 9 +# $server/conf in this directory 10 + 11 +client 12 +pull 13 + 14 +group nobody 15 + 16 +resolv-retry infinite 17 +nobind 18 + 19 +persist-key 20 +persist-tun 21 + 22 +log log 23 +mute-replay-warnings 24 +verb 3 25 +mute 10
Added vpn/vpn version [8e3b5d4148].
1 +#!/usr/bin/env bash 2 +# [ʞ] vpn 3 +# ~ lexi hale <lexi@hale.su> 4 +# ® affero general public license 5 +# $ vpn (join | part | info | clean | key) <name> 6 +# : vim:ft=bash 7 + 8 +# vpn is a simple wrapper around openvpn to make it suitable 9 +# for everyday use. it takes two arguments: the vpn, and 10 +# what to do with it. 11 +# - vpn join <vpn>: opens a connection to vpn <name> 12 +# - vpn part <vpn>: closes an active connection to <name> 13 +# - vpn info <vpn>: reports the status of of a vpn 14 +# - vpn key <host>: automatically provisions the client 15 +# with RSA keys from <host> and creates 16 +# a configuration file if one does not 17 +# already exist 18 +# - vpn part <vpn>: closes an active connection to <vpn> 19 +# - vpn help: display this text 20 +# 21 +# a number of environment variables affect the behavior of 22 +# vpn. these are listed in the source with their defaults 23 +# and an explantion of their function. if you do not wish 24 +# users to be able to change the behavior of vpn with 25 +# setenv, you must change the param invokation to a simple 26 +# assignment. 27 +# 28 +# note that you may want to add a visudo line allowing 29 +# %wheel or perhaps even all users to execute openvpn 30 +# without a password; otherwise, only sudoers will be able 31 +# to use vpn and the root password will be required for 32 +# every state change. 33 +__=$LINENO 34 + 35 +param(){ eval $1=\${$1:-$2}; } 36 + 37 +param vpn_basedir ~/opt/vpn 38 + # the directory in which vpn's logfiles are stored, 39 + # and possibly the script itself 40 + 41 +param vpn_confdir $vpn_basedir 42 + # the directory that contains the individual vpn 43 + # directories 44 + 45 +param vpn_global $vpn_basedir/conf 46 + # a configuration file that is applied to all vpns 47 + 48 +param vpn_srv_keydir /srv/vpn/ca 49 + # the directory on the server where vpn client keys 50 + # are stored 51 + 52 +param vpn_cn $(uname -n) 53 + # the name of the device / user / resource connecting 54 + # `vpn key` will use this value to determine which 55 + # client keys to download. i recommend a one-key-per- 56 + # device setup with the certificate CN used to assign 57 + # a name in the tunnel's DNS server, but one-key-per- 58 + # user or one-key-period setups are also possible. 59 + 60 +param TMPDIR /tmp 61 + # a directory for temporary files, preferably one that 62 + # does not persist across boots (e.g. a tmpfs) 63 + 64 +param USER $(whoami) 65 + # the user who should own all files and processes 66 + # created and destroyed by vpn 67 + 68 +param vpn_pidbox $TMPDIR/pid.$USER 69 + # a directory for storing pids in. this should be chmod 70 + # 700 and owned by the user invoking vpn, ideally 71 + 72 +param vpn_script $0 73 + # a path to the executable 74 + 75 +param vpn_scrname $(basename $vpn_script) 76 + # the name of the executable 77 + 78 +# thus ends the admin-configurable portion of this script. 79 +# abandon all hope, ye who enter here 80 + 81 +err(){ echo -e "\e[1;31merror:\e[m" $* ; exit 1; } 82 +assert(){ msg=$1; shift; test ! $@ && err $msg; } 83 + 84 +test "$1" == help || assert "incorrect number of arguments" $# -eq 2 85 + 86 +act=$1; target=$2 87 +vpnd=$vpn_confdir/$target 88 +conf=$vpnd/conf 89 + 90 +test "$act" == key && { 91 + mkdir -p $vpnd 92 + test -e $conf || { 93 + echo dev tun > $conf 94 + echo proto udp >> $conf 95 + echo remote $target 1194 >> $conf 96 + } 97 +} 98 + 99 +assert "target \e[1m$target\e[m does not exist!" -e $vpn_confdir/$target 100 +assert "target \e[1m$target\e[m has no configuration file" -e $conf 101 + 102 +pidfile="$vpn_pidbox/openvpn.$target" 103 + 104 +stale() { 105 + ((clean == 1)) && { 106 + echo " → deleting stale pidfile" 107 + rm -f $pidfile 108 + } || { 109 + echo -e " - run \e[1m$vpn_scrname clean\e[m to clean up" 110 + } 111 +} 112 + 113 +goodpid(){ 114 + test -e $pidfile || return 1 115 + local proc=$(ps ho fname $(cat $pidfile)) || return 2 116 + test "$proc" == openvpn || return 2 117 + return 0 118 +} 119 + 120 + 121 +case $act in 122 + # automatically provision machine 123 + ( key | setup | provision | download | dl | k ) 124 + scp $target:$vpn_srv_keydir/pki/{ca.crt,{issued,private}/$vpn_cn.\*} $vpnd/ || err "could not retrieve keys for \e[1m$target\e[m; ensure ssh is properly configured and machine keys are assigned to the correct user" ;; 125 + 126 + # connect to the openvpn server 127 + ( join | up | connect | con | start | j | u ) 128 + # don't clobber an existing connection 129 + goodpid && err "\e[1m$target\e[m is already up!" 130 + 131 + # make sure a private pid directory exists 132 + test ! -e $vpn_pidbox && 133 + mkdir -p $vpn_pidbox 134 + chmod 700 $vpn_pidbox 135 + 136 + # check and see if we're using automatic 137 + # host certificates; tell openvpn if so 138 + test -e $vpnd/ca.crt && { 139 + hostcert=$vpnd/$vpn_cn 140 + cmd=( 141 + --askpass 142 + --ca $vpnd/ca.crt 143 + --cert $hostcert.crt 144 + --key $hostcert.key 145 + ) 146 + } 147 + 148 + touch $pidfile # make sure invoker owns it 149 + chmod 600 $pidfile # bc fuck you, that's why 150 + sudo openvpn --daemon --config $vpn_global \ 151 + --config $conf \ 152 + --user $USER \ 153 + ${cmd[@]} \ 154 + --writepid $pidfile || rm $pidfile;; 155 + 156 + # kill an existing connection 157 + ( part | down | disc* | stop | p | d ) 158 + test -e $pidfile && { 159 + goodpid && { 160 + kill $(cat $pidfile) && rm -f $pidfile 161 + } || { 162 + echo -e "\e[1;33mwarn:\e[m pidfile exists but does not name an openvpn process" 163 + echo " → removing pidfile for safety" 164 + rm -f $pidfile 165 + } 166 + 167 + } || { 168 + echo -ne "\e[1mvpn $target\e[m is not up" 169 + } ;; 170 + 171 + # clean up dirty pidfiles 172 + ( clean | wipe | clear | fix | tidy ) clean=1 ;& 173 + # return profile status 174 + ( info | stat* | detail* | i ) 175 + echo -ne "\e[1mvpn $target:\e[m " 176 + test ! -e $pidfile && { 177 + echo -ne "\e[31mno\e[m current connection" 178 + pids=($(pidof openvpn)) 179 + let pidc=${#pids} 180 + ((pidc > 0)) && { 181 + echo ", but $pidc vpn instances are running" 182 + exit 2 183 + } || { echo; exit 0; } 184 + } || { 185 + echo -n "pidfile exists" 186 + proc=$(ps ho fname $(cat $pidfile)) 187 + (($? != 0)) && { 188 + echo ", but there are no processes with that pid" 189 + stale; exit 1 190 + } || test "$proc" == "openvpn" && { 191 + echo -e " and openvpn is \e[32mrunning\e[m" 192 + exit 0 193 + } || { 194 + echo -e " but named process is \e[31mnot a vpn instance!\e[m" 195 + stale; exit 1 196 + } 197 + } ;; 198 + ( help ) head -n $(expr $__ - 1) $vpn_script | 199 + tail -n $(expr $__ - 2); exit 255;; 200 + 201 + ( * ) err "action must be one of: join | part | info | clean" ;; 202 +esac 203 +