summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkali kaneko (leap communications) <kali@leap.se>2021-05-17 12:53:24 +0200
committerkali kaneko (leap communications) <kali@leap.se>2021-05-17 17:52:46 +0200
commit083f4095319b734f33f3e28a9f3234ff9cf6a7d7 (patch)
treed6e81c51862f1a7157d8e1de719e214df579104d
parent1d0bdcd6d82b1edcb56268198b242a5814a04fd9 (diff)
[feat] reuse certificate if found in config folder
-rw-r--r--docs/circumvention.rst25
-rw-r--r--pkg/vpn/certs.go34
-rw-r--r--pkg/vpn/main.go2
-rw-r--r--pkg/vpn/openvpn.go34
4 files changed, 82 insertions, 13 deletions
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")
}