From 86d30f2a2edc0d9b9c54b51258a6566e37476849 Mon Sep 17 00:00:00 2001 From: "kali kaneko (leap communications)" Date: Mon, 17 May 2021 17:33:40 +0200 Subject: [feat] retry if dns lookup fails --- pkg/vpn/bonafide/bonafide.go | 41 ++++++++++++++++++++++++++++++++++++++++- pkg/vpn/bonafide/eip_service.go | 7 +++++++ pkg/vpn/openvpn.go | 22 ++++++++++++++++++++-- 3 files changed, 67 insertions(+), 3 deletions(-) (limited to 'pkg') diff --git a/pkg/vpn/bonafide/bonafide.go b/pkg/vpn/bonafide/bonafide.go index fc1bc95..a9a7d85 100644 --- a/pkg/vpn/bonafide/bonafide.go +++ b/pkg/vpn/bonafide/bonafide.go @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 LEAP +// Copyright (C) 2018-2021 LEAP // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -75,6 +75,17 @@ type geoLocation struct { SortedGateways []geoGateway `json:"sortedGateways"` } +func getAPIAddr(provider string) string { + switch provider { + case "riseup.net": + return "198.252.153.107" + case "calyx.net": + return "162.247.73.194" + default: + return "" + } +} + // New Bonafide: Initializes a Bonafide object. By default, no Credentials are passed. func New() *Bonafide { certs := x509.NewCertPool() @@ -179,6 +190,17 @@ func (b *Bonafide) GetPemCertificate() ([]byte, error) { return ioutil.ReadAll(resp.Body) } +func (b *Bonafide) GetPemCertificateNoDNS() ([]byte, error) { + req, err := http.NewRequest("POST", b.getURLNoDNS("certv3"), strings.NewReader("")) + resp, err := b.client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + return ioutil.ReadAll(resp.Body) +} + func (b *Bonafide) getURL(object string) string { switch object { case "cert": @@ -192,6 +214,23 @@ func (b *Bonafide) getURL(object string) string { return "" } +func (b *Bonafide) getURLNoDNS(object string) string { + p := strings.ToLower(config.Provider) + base := "https://" + getAPIAddr(p) + "/" + switch object { + case "cert": + return base + certPathv1 + case "certv3": + return base + certPathv3 + case "auth": + return base + authPathv3 + case "eip": + return base + "3/config/eip-service.json" + } + log.Println("BUG: unknown url object") + return "" +} + func (b *Bonafide) maybeInitializeEIP() error { if b.eip == nil { err := b.fetchEipJSON() diff --git a/pkg/vpn/bonafide/eip_service.go b/pkg/vpn/bonafide/eip_service.go index d5dd751..5755b6c 100644 --- a/pkg/vpn/bonafide/eip_service.go +++ b/pkg/vpn/bonafide/eip_service.go @@ -83,6 +83,13 @@ func (b *Bonafide) fetchEipJSON() error { // TODO why exactly 1 retry? Make it configurable, for tests time.Sleep(retryFetchJSONSeconds * time.Second) resp, err = b.client.Post(eip3API, "", nil) + if err != nil { + // TODO it might be that it's not an error, but an empty file or whatever done + // by DNS poisoning. Should try to parse the file. + uri := b.getURLNoDNS("eip") + log.Println("Fetching ", uri) + resp, err = b.client.Post(uri, "", nil) + } } defer resp.Body.Close() diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go index 7cfa101..a568a32 100644 --- a/pkg/vpn/openvpn.go +++ b/pkg/vpn/openvpn.go @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 LEAP +// Copyright (C) 2018-2021 LEAP // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -177,6 +177,7 @@ func (b *Bitmask) startOpenVPN() error { } func (b *Bitmask) getCert() (certPath string, err error) { + failed := false persistentCertFile := filepath.Join(config.Path, strings.ToLower(config.Provider)+".pem") if _, err := os.Stat(persistentCertFile); !os.IsNotExist(err) && isValidCert(persistentCertFile) { // reuse cert. for the moment we're not writing one there, this is @@ -191,9 +192,26 @@ func (b *Bitmask) getCert() (certPath string, err error) { log.Println("Fetching certificate to", certPath) cert, err := b.bonafide.GetPemCertificate() if err != nil { - return "", err + log.Println(err) + failed = true } err = ioutil.WriteFile(certPath, cert, 0600) + if err != nil { + failed = true + } + } + } + if failed || !isValidCert(certPath) { + cert, err := b.bonafide.GetPemCertificateNoDNS() + if cert != nil { + log.Println("Successfully did certificate bypass") + err = nil + } else { + err = errors.New("Cannot get vpn certificate") + } + err = ioutil.WriteFile(certPath, cert, 0600) + if err != nil { + failed = true } } return certPath, err -- cgit v1.2.3