Fixed slave server crashed issue if the master is unvailable

This commit is contained in:
Ilya Sosnovsky 2020-11-19 20:08:55 +03:00
parent 9f8098ab03
commit bf37066475
5 changed files with 77 additions and 19 deletions

View File

@ -8,8 +8,8 @@ if [ -e "$SERVER_CERT" ]; then
echo "Found existing certs - reusing" echo "Found existing certs - reusing"
else else
if [ ${OPVN_ROLE:-"master"} = "slave" ]; then if [ ${OPVN_ROLE:-"master"} = "slave" ]; then
echo "Waiting for syncing data from master" echo "Waiting for initial sync data from master"
while [ $(wget -q localhost/api/sync/last -O - | wc -m) -lt 1 ] while [ $(wget -q localhost/api/sync/last/try -O - | wc -m) -lt 1 ]
do do
sleep 5 sleep 5
done done

View File

@ -1 +1,25 @@
# openvpn-web-ui # openvpn-admin
```
usage: openvpn-admin [<flags>]
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.
```

View File

@ -2,5 +2,5 @@
ifconfig-push {{ .ClientAddress }} 255.255.255.255 ifconfig-push {{ .ClientAddress }} 255.255.255.255
{{- end }} {{- end }}
{{- range $route := .CustomRoutes }} {{- range $route := .CustomRoutes }}
push "route {{ $route.Address }} {{ $route.Mask }}" # {{ $route.Description }} push "route {{ $route.Address }} {{ $route.Mask }}" ; {{ $route.Description }}
{{- end }} {{- end }}

View File

@ -262,7 +262,7 @@ new Vue({
.then(function(response) { .then(function(response) {
_this.serverRole = response.data.serverRole; _this.serverRole = response.data.serverRole;
if (_this.serverRole == "slave") { if (_this.serverRole == "slave") {
axios.request(axios_cfg('api/sync/last')) axios.request(axios_cfg('api/sync/last/successful'))
.then(function(response) { .then(function(response) {
_this.lastSync = response.data; _this.lastSync = response.data;
}); });

62
main.go
View File

@ -28,12 +28,12 @@ var (
listenHost = kingpin.Flag("listen.host","host for openvpn-admin").Default("0.0.0.0").String() 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() 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() 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() 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() 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() 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() masterSyncToken = kingpin.Flag("master.sync-token", "master host data sync security token").Default("justasimpleword").PlaceHolder("TOKEN").String()
openvpnServer = kingpin.Flag("ovpn.host","host for openvpn server").Default("127.0.0.1:7777").PlaceHolder("HOST:PORT").Strings() 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() 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() 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() mgmtListenPort = kingpin.Flag("mgmt.port","port for openvpn server mgmt interface").Default("8989").String()
@ -46,7 +46,8 @@ var (
certsArchivePath = "/tmp/" + certsArchiveFileName certsArchivePath = "/tmp/" + certsArchiveFileName
ccdArchivePath = "/tmp/" + ccdArchiveFileName ccdArchivePath = "/tmp/" + ccdArchiveFileName
lastSyncTime = "" lastSyncTime = ""
masterHostBsicAuth = false lastSuccessfulSyncTime = ""
masterHostBasicAuth = false
) )
type OpenvpnServer struct { type OpenvpnServer struct {
@ -198,6 +199,10 @@ func lastSyncTimeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, lastSyncTime) fmt.Fprint(w, lastSyncTime)
} }
func lastSuccessfulSyncTimeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, lastSuccessfulSyncTime)
}
func downloadCertsHandler(w http.ResponseWriter, r *http.Request) { func downloadCertsHandler(w http.ResponseWriter, r *http.Request) {
if *serverRole == "slave" { if *serverRole == "slave" {
http.Error(w, `{"status":"error"}`, http.StatusLocked) http.Error(w, `{"status":"error"}`, http.StatusLocked)
@ -238,7 +243,7 @@ func main() {
kingpin.Parse() kingpin.Parse()
if *masterBasicAuthPassword != "" && *masterBasicAuthUser != "" { if *masterBasicAuthPassword != "" && *masterBasicAuthUser != "" {
masterHostBsicAuth = true masterHostBasicAuth = true
} }
fmt.Println("Bind: http://" + *listenHost + ":" + *listenPort) fmt.Println("Bind: http://" + *listenHost + ":" + *listenPort)
@ -261,7 +266,8 @@ func main() {
http.HandleFunc("/api/user/ccd", userShowCcdHandler) http.HandleFunc("/api/user/ccd", userShowCcdHandler)
http.HandleFunc("/api/user/ccd/apply", userApplyCcdHandler) 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(downloadCertsApiUrl, downloadCertsHandler)
http.HandleFunc(downloadCcdApiUrl, downloadCddHandler) http.HandleFunc(downloadCcdApiUrl, downloadCddHandler)
@ -659,9 +665,9 @@ func downloadCerts() bool {
if fExist(certsArchivePath) { if fExist(certsArchivePath) {
fDelete(certsArchivePath) fDelete(certsArchivePath)
} }
err := fDownload(certsArchivePath, *masterHost + downloadCertsApiUrl + "?token=" + *masterSyncToken, masterHostBsicAuth) err := fDownload(certsArchivePath, *masterHost + downloadCertsApiUrl + "?token=" + *masterSyncToken, masterHostBasicAuth)
if err != nil { if err != nil {
log.Fatal(err) log.Println(err)
return false return false
} }
@ -673,9 +679,9 @@ func downloadCcd() bool {
fDelete(ccdArchivePath) fDelete(ccdArchivePath)
} }
err := fDownload(ccdArchivePath, *masterHost + downloadCcdApiUrl + "?token=" + *masterSyncToken, masterHostBsicAuth) err := fDownload(ccdArchivePath, *masterHost + downloadCcdApiUrl + "?token=" + *masterSyncToken, masterHostBasicAuth)
if err != nil { if err != nil {
log.Fatal(err) log.Println(err)
return false return false
} }
@ -705,13 +711,41 @@ func unArchiveCcd() {
} }
func syncDataFromMaster() { func syncDataFromMaster() {
downloadCerts() log.Println("Downloading archives from master")
downloadCcd() retryCountMax := 3
unArchiveCerts() certsDownloadFailed := true
unArchiveCcd() 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") 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() { func syncWithMaster() {