From 083f4095319b734f33f3e28a9f3234ff9cf6a7d7 Mon Sep 17 00:00:00 2001 From: "kali kaneko (leap communications)" Date: Mon, 17 May 2021 12:53:24 +0200 Subject: [feat] reuse certificate if found in config folder --- docs/circumvention.rst | 25 +++++++++++++++++++++++++ pkg/vpn/certs.go | 34 ++++++++++++++++++++++++++++++++++ pkg/vpn/main.go | 2 +- pkg/vpn/openvpn.go | 34 ++++++++++++++++++++++------------ 4 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 docs/circumvention.rst create mode 100644 pkg/vpn/certs.go diff --git a/docs/circumvention.rst b/docs/circumvention.rst new file mode 100644 index 0000000..8c220cc --- /dev/null +++ b/docs/circumvention.rst @@ -0,0 +1,25 @@ +Censorship Circumvention +================================================================================ + +This document contains some advice for using BitmaskVPN for censorship +circumvention. + +Bootstrapping the connection +----------------------------- + +There are two different steps where circumvention can be used: boostrapping the +connection (getting a certificate and the configuration files) and using an +obfuscated transport protocol. At the moment RiseupVPN offers obfs4 transport +"bridges" (you can try them with the `--obfs4` command line argument). For the +initial bootstrap, there are a couple of techniques that will be attempted. + +Getting certificates off-band +----------------------------- + +As a last resort, you can place a valid certificate in the config folder (name +it after the provider domain). You might have downloaded this cert with Tor, +using a socks proxy etc... + + ~/.config/leap/riseup.net.pem + +When the certificate expires you will need to download a new one. diff --git a/pkg/vpn/certs.go b/pkg/vpn/certs.go new file mode 100644 index 0000000..300871e --- /dev/null +++ b/pkg/vpn/certs.go @@ -0,0 +1,34 @@ +package vpn + +import ( + "crypto/x509" + "encoding/pem" + "io/ioutil" + "log" + "time" +) + +func isValidCert(path string) bool { + data, err := ioutil.ReadFile(path) + if err != nil { + return false + } + // skip private key, but there should be one + _, rest := pem.Decode(data) + certBlock, rest := pem.Decode(rest) + if len(rest) != 0 { + log.Println("ERROR bad cert data") + return false + } + cert, err := x509.ParseCertificate(certBlock.Bytes) + loc, _ := time.LoadLocation("UTC") + expires := cert.NotAfter + tomorrow := time.Now().In(loc).Add(24 * time.Hour) + + if !expires.After(tomorrow) { + return false + } else { + log.Println("DEBUG We have a valid cert:", path) + return true + } +} diff --git a/pkg/vpn/main.go b/pkg/vpn/main.go index f40366c..826e5d4 100644 --- a/pkg/vpn/main.go +++ b/pkg/vpn/main.go @@ -68,7 +68,7 @@ func Init() (*Bitmask, error) { } */ - err = ioutil.WriteFile(b.getCaCertPath(), config.CaCert, 0600) + err = ioutil.WriteFile(b.getTempCaCertPath(), config.CaCert, 0600) go b.openvpnManagement() return &b, err diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go index 4dad0e2..7cfa101 100644 --- a/pkg/vpn/openvpn.go +++ b/pkg/vpn/openvpn.go @@ -22,9 +22,11 @@ import ( "log" "os" "path" + "path/filepath" "strconv" "strings" + "0xacab.org/leap/bitmask-vpn/pkg/config" "0xacab.org/leap/shapeshifter" ) @@ -167,7 +169,7 @@ func (b *Bitmask) startOpenVPN() error { "--verb", "3", "--management-client", "--management", openvpnManagementAddr, openvpnManagementPort, - "--ca", b.getCaCertPath(), + "--ca", b.getTempCaCertPath(), "--cert", b.certPemPath, "--key", b.certPemPath, "--persist-tun") @@ -175,17 +177,25 @@ func (b *Bitmask) startOpenVPN() error { } func (b *Bitmask) getCert() (certPath string, err error) { - certPath = b.getCertPemPath() - - if _, err := os.Stat(certPath); os.IsNotExist(err) { - log.Println("Fetching certificate to", certPath) - cert, err := b.bonafide.GetPemCertificate() - if err != nil { - return "", err + 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 + // only to allow users to get certs off-band and place them there + // as a last-resort fallback for circumvention. + certPath = persistentCertFile + err = nil + } else { + // download one fresh + certPath = b.getTempCertPemPath() + if _, err := os.Stat(certPath); os.IsNotExist(err) { + log.Println("Fetching certificate to", certPath) + cert, err := b.bonafide.GetPemCertificate() + if err != nil { + return "", err + } + err = ioutil.WriteFile(certPath, cert, 0600) } - err = ioutil.WriteFile(certPath, cert, 0600) } - return certPath, err } @@ -299,10 +309,10 @@ func (b *Bitmask) UseTransport(transport string) error { return nil } -func (b *Bitmask) getCertPemPath() string { +func (b *Bitmask) getTempCertPemPath() string { return path.Join(b.tempdir, "openvpn.pem") } -func (b *Bitmask) getCaCertPath() string { +func (b *Bitmask) getTempCaCertPath() string { return path.Join(b.tempdir, "cacert.pem") } -- cgit v1.2.3