From 3632705e1c713570d41bad34aab633fa15394bec Mon Sep 17 00:00:00 2001 From: Patrick MARIE Date: Wed, 6 Apr 2022 20:51:58 +0200 Subject: [PATCH] Initial commit --- .gitignore | 1 + README.md | 22 +++++++++ go.mod | 3 ++ main.go | 115 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/linux.sh | 76 +++++++++++++++++++++++++++++++ 5 files changed, 217 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go create mode 100755 scripts/linux.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d477788 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +light-vpn diff --git a/README.md b/README.md new file mode 100644 index 0000000..0810837 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# LightVPN + +An alternative to AVPNC for Fedora users. + +## How ? + +Compile: + +```sh +$ go build +``` + +Run: + +```sh +$ sudo ./light-vpn -ovpn /path/to/corp-saml-aviatrix-vpn.ovpn +Using configuration file is [/home/mycroft/.downloads/corp-saml-aviatrix-vpn.ovpn]. +Please now go to https://prod.aviatrixsystems.com/flask/saml/login/avxcorpvpn. +Got your token! Email is: pmarie@aviatrix.com +Launching OpenVPN. Check log file: /tmp/openvpn-avx.log +... +``` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d642b87 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/mavxrie/light-vpn + +go 1.18 diff --git a/main.go b/main.go new file mode 100644 index 0000000..14fd8bd --- /dev/null +++ b/main.go @@ -0,0 +1,115 @@ +package main + +import ( + "encoding/json" + "errors" + "flag" + "fmt" + "log" + "net/http" + "os" + "os/exec" +) + +type Token struct { + Email string + Token string +} + +var ovpnFile string +var logFile string = "/tmp/openvpn-avx.log" +var samlCorpUrl string = "https://prod.aviatrixsystems.com/flask/saml/login/avxcorpvpn" + +func init() { + flag.StringVar(&ovpnFile, "ovpn", "corp-saml-aviatrix-vpn.ovpn", "The OpenVPN configuration file") +} + +func checkOpenVPNFile() error { + if _, err := os.Stat(ovpnFile); errors.Is(err, os.ErrNotExist) { + fmt.Fprintf(os.Stderr, "Given OpenVPN file [%s] could not be found.\n", ovpnFile) + return err + } + + fmt.Printf("Using configuration file is [%s].\n", ovpnFile) + + return nil +} + +func writeTempCredentials(token Token) (string, error) { + f, err := os.CreateTemp("", "vpn") + if err != nil { + return "", err + } + + fileContent := fmt.Sprintf("%s\n%s", token.Email, token.Token) + if _, err := f.Write([]byte(fileContent)); err != nil { + return "", err + } + + if err := f.Close(); err != nil { + return "", err + } + + return f.Name(), nil +} + +func localServer(tokenChannel chan<- Token) { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + var token Token + + err := json.Unmarshal([]byte(r.URL.Path[1:]), &token) + if err != nil { + log.Fatalf("Could not decode http response: %s (Reason: %s)\n", r.URL.Path[1:], err) + return + } + + w.Header().Set("Access-Control-Allow-Origin", "*") + fmt.Fprintf(w, "SuccessAviatrix") + + tokenChannel <- token + }) + + log.Fatal(http.ListenAndServe("127.0.0.1:15395", nil)) +} + +func main() { + flag.Parse() + + fmt.Println("Hello World!") + + if checkOpenVPNFile() != nil { + return + } + + tokenChannel := make(chan Token) + // Open a quick local httpd before redirecting user to go to saml auth page. + go localServer(tokenChannel) + + fmt.Printf("Please now go to %s.\n", samlCorpUrl) + + token := <-tokenChannel + + tmpCredentialsFile, err := writeTempCredentials(token) + if err != nil { + log.Fatal(err) + } + defer os.Remove(tmpCredentialsFile) + + fmt.Printf("Got your token! Email is: %s\n", token.Email) + fmt.Printf("Launching OpenVPN. Check log file: %s\n", logFile) + + cmd := exec.Command( + "/usr/sbin/openvpn", + "--config", ovpnFile, + "--auth-user-pass", tmpCredentialsFile, + "--script-security", "2", "--up-restart", "--up", "scripts/linux.sh", "--down", "scripts/linux.sh", + "--setenv", "IV_PLAT", "linux", "--setenv", "IV_GUI_VER", "AVPNC-2.14.14", "--push-peer-info", "--log", logFile, + ) + + err = cmd.Run() + if err != nil { + log.Fatal(err) + } + + fmt.Println("Bye!") +} diff --git a/scripts/linux.sh b/scripts/linux.sh new file mode 100755 index 0000000..d96b1a1 --- /dev/null +++ b/scripts/linux.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# +# Parses DHCP options from openvpn to update resolv.conf +# To use set as 'up' and 'down' script in your openvpn *.conf: +# up /etc/openvpn/update-resolv-conf +# down /etc/openvpn/update-resolv-conf +# +# Used snippets of resolvconf script by Thomas Hood +# and Chris Hanson +# Licensed under the GNU GPL. See /usr/share/common-licenses/GPL. +# 07/2013 colin@daedrum.net Fixed intet name +# 05/2006 chlauber@bnc.ch +# +# Example envs set from openvpn: +# foreign_option_1='dhcp-option DNS 193.43.27.132' +# foreign_option_2='dhcp-option DNS 193.43.27.133' +# foreign_option_3='dhcp-option DOMAIN be.bnc.ch' +# foreign_option_4='dhcp-option DOMAIN-SEARCH bnc.local' + +## You might need to set the path manually here, i.e. +RESOLVCONF=`which resolvconf` +RESOLVCONF=/usr/bin/x-www-browser +if [[ -z "$RESOLVCONF" ]]; then + if [ -x /usr/sbin/resolvconf ]; then + RESOLVCONF=/sbin/resolvconf + elif [ -x /usr/bin/resolvconf ]; then + RESOLVCONF=/usr/bin/resolvconf + elif [ -x /sbin/resolvconf ]; then + RESOLVCONF=/sbin/resolvconf + else + RESOLVCONF=/bin/resolvconf + fi +fi + +[ -x "$RESOLVCONF" ] || exit 0 + +case $script_type in + +up) + for optionname in ${!foreign_option_*} ; do + option="${!optionname}" + echo $option + part1=$(echo "$option" | cut -d " " -f 1) + if [ "$part1" == "dhcp-option" ] ; then + part2=$(echo "$option" | cut -d " " -f 2) + part3=$(echo "$option" | cut -d " " -f 3) + if [ "$part2" == "DNS" ] ; then + IF_DNS_NAMESERVERS="$IF_DNS_NAMESERVERS $part3" + fi + if [[ "$part2" == "DOMAIN" || "$part2" == "DOMAIN-SEARCH" ]] ; then + IF_DNS_SEARCH="$IF_DNS_SEARCH $part3" + fi + fi + done + R="" + if [ "$IF_DNS_SEARCH" ]; then + R="search " + for DS in $IF_DNS_SEARCH ; do + R="${R} $DS" + done + R="${R} +" + fi + + for NS in $IF_DNS_NAMESERVERS ; do + R="${R}nameserver $NS +" + done + echo -n "$R" | $RESOLVCONF -a "${dev}.vpn" + $RESOLVCONF -u || true + ;; +down) + $RESOLVCONF -d "${dev}.vpn" + $RESOLVCONF -u || true + ;; +esac