From: Ben L. <be...@bd...> - 2006-10-13 13:17:22
|
This describes a mechanism for integrating OpenVPN client assignments into a local (server) DNS, such that you can reference VPN clients by name. e.g. 'common-name.vpn.example.net', where common-name is the VPN client's authenticated username (typically the certificate's Common Name). The learn-address.sh script below maintains a separate /etc/hosts- style file, adding and removing (commenting out) IP - name records as openvpn clients connect and disconnect. Using this with the dnsmasq DNS server's support for an 'additional hosts' file gives the desired result. Server setup: - OpenVPN 2.0.x - dnsmasq 2.27 (or equivalent) - the learn-address.sh script below Client setup: - client certificate's Common Name will be used as the client's hostname Edit your server config files, and create the learn-address script as follows: === openvpn.conf (relevant extracts) === learn-address /var/lib/openvpn/learn-address.sh === dnsmasq.conf (relevant extracts) === addn-hosts=/etc/hosts.openvpn-clients === /var/lib/openvpn/learn-address.sh === #!/bin/sh # openvpn learn-address script to manage a hosts-like file # - intended to allow dnsmasq to resolve openvpn clients # addn-hosts=/etc/hosts.openvpn-clients # - written for openwrt (busybox), but should work most anywhere # # Changelog # 2006-10-13 BDL original # replace with a sub-domain of your domain, use a sub-domain to prevent VPN clients from stealing existing names DOMAIN=vpn.example.net HOSTS=/etc/hosts.openvpn-clients h=$(/usr/bin/basename "$HOSTS") LOCKFILE="/var/run/$h.lock" IP="$2" CN="$3" case "$1" in add|update) if [ -z "$IP" -o -z "$CN" ]; then echo "$0: IP and/or Common Name not provided" >&2 exit 0 fi ;; delete) if [ -z "$IP" ]; then echo "$0: IP not provided" >&2 exit 0 fi ;; *) echo "$0: unknown operation [$1]" >&2 exit 1 ;; esac # serialise concurrent accesses [ -x /bin/lock ] && /bin/lock "$LOCKFILE" # clean up IP if we can [ -x /bin/ipcalc ] && eval $(ipcalc "$IP") FQDN="$CN.$DOMAIN" # busybox mktemp must have exactly six X's t=$(/bin/mktemp "/tmp/$h.XXXXXX") if [ $? -ne 0 ]; then echo "$0: mktemp failed" >&2 exit 1 fi case "$1" in add|update) /usr/bin/awk ' # update/uncomment address|FQDN with new record, drop any duplicates: $1 == "'"$IP"'" || $1 == "#'"$IP"'" || $2 == "'"$FQDN"'" \ { if (!m) print "'"$IP"'\t'"$FQDN"'"; m=1; next } { print } END { if (!m) print "'"$IP"'\t'"$FQDN"'" } # add new address to end ' "$HOSTS" > "$t" && cat "$t" > "$HOSTS" ;; delete) /usr/bin/awk ' # no FQDN, comment out all matching addresses (should only be one) $1 == "'"$IP"'" { print "#" $0; next } { print } ' "$HOSTS" > "$t" && cat "$t" > "$HOSTS" ;; esac # signal dnsmasq to reread hosts file /bin/kill -HUP $(cat /var/run/dnsmasq.pid) /bin/rm "$t" [ -x /bin/lock ] && /bin/lock -u "$LOCKFILE" |