From bf37066475f98b0c7fed88cd02a2d6406a2d4b1b Mon Sep 17 00:00:00 2001 From: Ilya Sosnovsky Date: Thu, 19 Nov 2020 20:08:55 +0300 Subject: [PATCH] Fixed slave server crashed issue if the master is unvailable --- .werffiles/configure.sh | 4 +-- README.md | 26 ++++++++++++++++- ccd.tpl | 2 +- frontend/src/main.js | 2 +- main.go | 62 +++++++++++++++++++++++++++++++---------- 5 files changed, 77 insertions(+), 19 deletions(-) diff --git a/.werffiles/configure.sh b/.werffiles/configure.sh index d9ab8a5..f439248 100644 --- a/.werffiles/configure.sh +++ b/.werffiles/configure.sh @@ -8,8 +8,8 @@ if [ -e "$SERVER_CERT" ]; then echo "Found existing certs - reusing" else if [ ${OPVN_ROLE:-"master"} = "slave" ]; then - echo "Waiting for syncing data from master" - while [ $(wget -q localhost/api/sync/last -O - | wc -m) -lt 1 ] + echo "Waiting for initial sync data from master" + while [ $(wget -q localhost/api/sync/last/try -O - | wc -m) -lt 1 ] do sleep 5 done diff --git a/README.md b/README.md index 0f0c5ec..ecef39a 100644 --- a/README.md +++ b/README.md @@ -1 +1,25 @@ -# openvpn-web-ui \ No newline at end of file +# openvpn-admin +``` +usage: openvpn-admin [] + +Flags: + --help Show context-sensitive help (also try --help-long and --help-man). + --listen.host="0.0.0.0" host(s) for openvpn-admin + --listen.port="8080" port for openvpn-admin + --role="master" server role master or slave + --master.host="http://127.0.0.1" url for master server + --master.basic-auth.user="" user for basic auth on master server url + --master.basic-auth.password="" password for basic auth on master server url + --master.sync-frequency=600 master host data sync frequency in seconds. + --master.sync-token=TOKEN master host data sync security token + --ovpn.host=HOST:PORT ... host for openvpn server + --ovpn.network="172.16.100.0/24" network for openvpn server + --mgmt.host="127.0.0.1" host for openvpn server mgmt interface + --mgmt.port="8989" port for openvpn server mgmt interface + --easyrsa.path="/mnt/easyrsa" path to easyrsa dir + --easyrsa.index-path="/mnt/easyrsa/pki/index.txt" + path to easyrsa index file. + --ccd.path="/mnt/ccd" path to client-config-dir + --static.path="./static" path to static dir + --debug Enable debug mode. +``` \ No newline at end of file diff --git a/ccd.tpl b/ccd.tpl index a197fd9..2a6fa00 100644 --- a/ccd.tpl +++ b/ccd.tpl @@ -2,5 +2,5 @@ ifconfig-push {{ .ClientAddress }} 255.255.255.255 {{- end }} {{- range $route := .CustomRoutes }} -push "route {{ $route.Address }} {{ $route.Mask }}" # {{ $route.Description }} +push "route {{ $route.Address }} {{ $route.Mask }}" ; {{ $route.Description }} {{- end }} diff --git a/frontend/src/main.js b/frontend/src/main.js index aeca17c..bff18d6 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -262,7 +262,7 @@ new Vue({ .then(function(response) { _this.serverRole = response.data.serverRole; if (_this.serverRole == "slave") { - axios.request(axios_cfg('api/sync/last')) + axios.request(axios_cfg('api/sync/last/successful')) .then(function(response) { _this.lastSync = response.data; }); diff --git a/main.go b/main.go index c7e4bdd..665ea5a 100644 --- a/main.go +++ b/main.go @@ -28,12 +28,12 @@ var ( listenHost = kingpin.Flag("listen.host","host for openvpn-admin").Default("0.0.0.0").String() listenPort = kingpin.Flag("listen.port","port for openvpn-admin").Default("8080").String() serverRole = kingpin.Flag("role","server role master or slave").Default("master").HintOptions("master", "slave").String() - masterHost = kingpin.Flag("master.host","Url for master server").Default("http://127.0.0.1").String() + masterHost = kingpin.Flag("master.host","url for master server").Default("http://127.0.0.1").String() masterBasicAuthUser = kingpin.Flag("master.basic-auth.user","user for basic auth on master server url").Default("").String() masterBasicAuthPassword = kingpin.Flag("master.basic-auth.password","password for basic auth on master server url").Default("").String() masterSyncFrequency = kingpin.Flag("master.sync-frequency", "master host data sync frequency in seconds.").Default("600").Int() - masterSyncToken = kingpin.Flag("master.sync-token", "master host data sync security token").Required().String() - openvpnServer = kingpin.Flag("ovpn.host","host for openvpn server").Default("127.0.0.1:7777").PlaceHolder("HOST:PORT").Strings() + masterSyncToken = kingpin.Flag("master.sync-token", "master host data sync security token").Default("justasimpleword").PlaceHolder("TOKEN").String() + openvpnServer = kingpin.Flag("ovpn.host","host(s) for openvpn server").Default("127.0.0.1:7777").PlaceHolder("HOST:PORT").Strings() openvpnNetwork = kingpin.Flag("ovpn.network","network for openvpn server").Default("172.16.100.0/24").String() mgmtListenHost = kingpin.Flag("mgmt.host","host for openvpn server mgmt interface").Default("127.0.0.1").String() mgmtListenPort = kingpin.Flag("mgmt.port","port for openvpn server mgmt interface").Default("8989").String() @@ -46,7 +46,8 @@ var ( certsArchivePath = "/tmp/" + certsArchiveFileName ccdArchivePath = "/tmp/" + ccdArchiveFileName lastSyncTime = "" - masterHostBsicAuth = false + lastSuccessfulSyncTime = "" + masterHostBasicAuth = false ) type OpenvpnServer struct { @@ -198,6 +199,10 @@ func lastSyncTimeHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, lastSyncTime) } +func lastSuccessfulSyncTimeHandler(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, lastSuccessfulSyncTime) +} + func downloadCertsHandler(w http.ResponseWriter, r *http.Request) { if *serverRole == "slave" { http.Error(w, `{"status":"error"}`, http.StatusLocked) @@ -238,7 +243,7 @@ func main() { kingpin.Parse() if *masterBasicAuthPassword != "" && *masterBasicAuthUser != "" { - masterHostBsicAuth = true + masterHostBasicAuth = true } fmt.Println("Bind: http://" + *listenHost + ":" + *listenPort) @@ -261,7 +266,8 @@ func main() { http.HandleFunc("/api/user/ccd", userShowCcdHandler) http.HandleFunc("/api/user/ccd/apply", userApplyCcdHandler) - http.HandleFunc("/api/sync/last", lastSyncTimeHandler) + http.HandleFunc("/api/sync/last/try", lastSyncTimeHandler) + http.HandleFunc("/api/sync/last/successful", lastSuccessfulSyncTimeHandler) http.HandleFunc(downloadCertsApiUrl, downloadCertsHandler) http.HandleFunc(downloadCcdApiUrl, downloadCddHandler) @@ -659,9 +665,9 @@ func downloadCerts() bool { if fExist(certsArchivePath) { fDelete(certsArchivePath) } - err := fDownload(certsArchivePath, *masterHost + downloadCertsApiUrl + "?token=" + *masterSyncToken, masterHostBsicAuth) + err := fDownload(certsArchivePath, *masterHost + downloadCertsApiUrl + "?token=" + *masterSyncToken, masterHostBasicAuth) if err != nil { - log.Fatal(err) + log.Println(err) return false } @@ -673,9 +679,9 @@ func downloadCcd() bool { fDelete(ccdArchivePath) } - err := fDownload(ccdArchivePath, *masterHost + downloadCcdApiUrl + "?token=" + *masterSyncToken, masterHostBsicAuth) + err := fDownload(ccdArchivePath, *masterHost + downloadCcdApiUrl + "?token=" + *masterSyncToken, masterHostBasicAuth) if err != nil { - log.Fatal(err) + log.Println(err) return false } @@ -705,13 +711,41 @@ func unArchiveCcd() { } func syncDataFromMaster() { - downloadCerts() - downloadCcd() + log.Println("Downloading archives from master") + retryCountMax := 3 - unArchiveCerts() - unArchiveCcd() + certsDownloadFailed := true + ccdDownloadFailed := true + + certsDownloadRetries := 0 + ccdDownloadRetries := 0 + + for certsDownloadFailed && certsDownloadRetries < retryCountMax { + certsDownloadRetries += 1 + if downloadCerts() { + certsDownloadFailed = false + log.Println("Decompression certs archive from master") + unArchiveCerts() + } else { + log.Printf("WARNING: something goes wrong during downloading certs from master. Attempt %d", certsDownloadRetries) + } + } + + for ccdDownloadFailed && ccdDownloadRetries < retryCountMax { + ccdDownloadRetries += 1 + if downloadCcd() { + ccdDownloadFailed = false + log.Println("Decompression ccd archive from master") + unArchiveCcd() + } else { + log.Printf("WARNING: something goes wrong during downloading certs from master. Attempt %d", ccdDownloadRetries) + } + } lastSyncTime = time.Now().Format("2006-01-02 15:04:05") + if !ccdDownloadFailed && !certsDownloadFailed { + lastSuccessfulSyncTime = time.Now().Format("2006-01-02 15:04:05") + } } func syncWithMaster() {