Skip to content

Commit

Permalink
hardcode openvpn endpoints under ooni infra
Browse files Browse the repository at this point in the history
changing the experiment as per request, to satisfy reqs for shipping the
experiment in time for Aug 2024 release.

Initially I had some concerns about this approach, but it seems to work
as long it's ensured that the server has `duplicate-cn` key in its
config, and `ping-restart` is set sufficiently low. empirically, it
seems to me that handshakes do not successfully finish if they happen
too soon back-to-back.  Needs to further investigate what's the cause,
better logging of what's happening will definitely need another release
of minivpn. I don't have time to cut a new minivpn release at this point
before the august releae of probe-cli.

In a different PR, I will attempt to ship a bunch more of certificates so
that I can minimize the likelihood of two probes having the same
certificate, in the same spirit of the work done for the wireguard probe.

For what we saw from real-data, the order of magnitude of expected
probes executing the experimental card is in the range of 100 per period
of 5 minutes.
  • Loading branch information
ainghazal committed Jul 28, 2024
1 parent 2df2cab commit 209a238
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 8 deletions.
6 changes: 3 additions & 3 deletions internal/experiment/openvpn/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ func (e *endpoint) AsInputURI() string {
return url.String()
}

// APIEnabledProviders is the list of providers that the stable API Endpoint knows about.
// This array will be a subset of the keys in defaultOptionsByProvider, but it might make sense
// to still register info about more providers that the API officially knows about.
// APIEnabledProviders is the list of providers that the stable API Endpoint and/or this
// experiment knows about.
var APIEnabledProviders = []string{
"riseupvpn",
"oonivpn",
}

// isValidProvider returns true if the provider is found as key in the array of [APIEnabledProviders].
Expand Down
2 changes: 1 addition & 1 deletion internal/experiment/openvpn/openvpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

const (
testName = "openvpn"
testVersion = "0.1.4"
testVersion = "0.1.5"
openVPNProtocol = "openvpn"
)

Expand Down
36 changes: 32 additions & 4 deletions internal/experiment/openvpn/richerinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,18 @@ func (tl *targetLoader) Load(ctx context.Context) ([]model.ExperimentTarget, err
// If inputs and files are all empty and there are no options, let's use the backend
if len(tl.loader.StaticInputs) <= 0 && len(tl.loader.SourceFiles) <= 0 &&
reflectx.StructOrStructPtrIsZero(tl.options) {
return tl.loadFromBackend(ctx)
targets, err := tl.loadFromBackend(ctx)
if err == nil {
return targets, nil
}
}

tl.session.Logger().Warn("Error fetching OpenVPN targets from backend")

// Otherwise, attempt to load the static inputs from CLI and files
inputs, err := targetloading.LoadStatic(tl.loader)

// Handle the case where we couldn't load from CLI or files
// Handle the case where we couldn't load from CLI or files:
if err != nil {
return nil, err
}
Expand All @@ -106,11 +111,34 @@ func (tl *targetLoader) Load(ctx context.Context) ([]model.ExperimentTarget, err
URL: input,
})
}
if len(targets) > 0 {
return targets, nil
}

// Return the hardcoded endpoints.
return tl.loadFromDefaultEndpoints()
}

func (tl *targetLoader) loadFromDefaultEndpoints() ([]model.ExperimentTarget, error) {
tl.session.Logger().Info("Using default OpenVPN endpoints")
targets := []model.ExperimentTarget{}
if udp, err := defaultOONIOpenVPNTargetUDP(); err == nil {
targets = append(targets,
&Target{
Config: defaultOONIOpenVPNConfig,
URL: udp,
})
}
if tcp, err := defaultOONIOpenVPNTargetTCP(); err == nil {
targets = append(targets,
&Target{
Config: defaultOONIOpenVPNConfig,
URL: tcp,
})
}
return targets, nil
}

// TODO(https://github.com/ooni/probe/issues/2755): make the code that fetches experiment private
// and let the common code export just the bare minimum to make this possible.
func (tl *targetLoader) loadFromBackend(ctx context.Context) ([]model.ExperimentTarget, error) {
if tl.options.Provider == "" {
tl.options.Provider = defaultProvider
Expand Down
53 changes: 53 additions & 0 deletions internal/experiment/openvpn/targets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package openvpn

import (
"fmt"
"net"
)

const defaultOpenVPNEndpoint = "openvpn-server1.ooni.io"

// this is a safety toggle: it's on purpose that the experiment will receive no
// input if the resolution fails. This also implies that we have no way of knowing if this
// target has been blocked at the level of DNS.
func resolveTarget() (string, error) {
ips, err := net.LookupIP(defaultOpenVPNEndpoint)
if err != nil {
return "", err
}
if len(ips) == 0 {
return "", fmt.Errorf("cannot resolve %v", defaultOpenVPNEndpoint)
}
return ips[0].String(), nil
}

func defaultOONITargetURL(ip string) string {
return "openvpn://oonivpn.corp/?address=" + ip + ":1194"
}

func defaultOONIOpenVPNTargetUDP() (string, error) {
ip, err := resolveTarget()
if err != nil {
return "", err
}
return defaultOONITargetURL(ip) + "&transport=udp", nil
}

func defaultOONIOpenVPNTargetTCP() (string, error) {
ip, err := resolveTarget()
if err != nil {
return "", err
}
return defaultOONITargetURL(ip) + "&transport=tcp", nil
}

var defaultOONIOpenVPNConfig = &Config{
Auth: "SHA512",
Cipher: "AES-256-GCM",
Compress: "stub",
Provider: "oonivpn",
Obfuscation: "none",
SafeCA: "-----BEGIN CERTIFICATE-----\nMIIDbzCCAlegAwIBAgIUVZz0MWBrsd26OIEccP08bNv+bScwDQYJKoZIhvcNAQEL\nBQAwIjEgMB4GA1UEAwwXb3BlbnZwbi1zZXJ2ZXIxLm9vbmkuaW8wHhcNMjQwNzI4\nMTE0NzQwWhcNMzQwNzI2MTE0NzQwWjAiMSAwHgYDVQQDDBdvcGVudnBuLXNlcnZl\ncjEub29uaS5pbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKOkPmCu\nYpAOue+y46rS1dnu+t1JINmvjO+Z2s7nezQMmEgP6o06pjrb8YlLByspGn/y2u7x\nFv2G86kWvRG+cpQgc2xBsEqRq7j5n45j51pat6TKt4c9Ejjnq6kGiqs3W3zDwnn+\nkx3KuvkmnOXkVQfHsUmVaS7fQpf0586ftOC7DenOvJV9LosBEIGyLyFCipaqh0eX\n6UfSGmr8tAqSfoWj8J62JBsP+U0MoLtHpRXLn2jyE/2re2mcsFLG8nRqHpTy8LGM\n6xT7c9JZSR7WiYNXB3UFBUcOpvLZ4ru6sa0BdXJiM8WQhywjVWtnM9UPf09ct57K\nMCdjWhwR81SaVAsCAwEAAaOBnDCBmTAdBgNVHQ4EFgQUOhvQMsDoG1Iw1g/w3sFp\n7BtVqIQwXQYDVR0jBFYwVIAUOhvQMsDoG1Iw1g/w3sFp7BtVqIShJqQkMCIxIDAe\nBgNVBAMMF29wZW52cG4tc2VydmVyMS5vb25pLmlvghRVnPQxYGux3bo4gRxw/Txs\n2/5tJzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOC\nAQEAoiN+S2BSMTYVA5ydWWCmfUDN30QiD2Wb3Of7ReLfG8dN4dMXULbDpzDgMl6/\nGUfOzrnZytm+ctANIQkmwf7iNcDrxLQWuw3HlvXmWLvaXA8aEi608j5dh30b6CZ8\nRSbckRYjo6oPltsmDzUG56K7NLBk9CnmmwzfJ4Rk/gEj5aoo7/AfkYB1zDaV/QBp\n60eKZ6dm6CutGBPZB0rAlBomKrKck51iU1cmJUS/RZZsZuGa6P4T2sZC20g8psOm\ngzQY31eQuTcexEddjrLqZSzVK4ZNDpycfkd1G2u+XWf3W/U2c7BAY0LFt7tieC7p\nHov5K6t2+k9xsw0vFtdDIPm4SA==\n-----END CERTIFICATE-----\n",
SafeCert: "-----BEGIN CERTIFICATE-----\nMIIDcTCCAlmgAwIBAgIRAJU2B64KWje6NlskJbfZomAwDQYJKoZIhvcNAQELBQAw\nIjEgMB4GA1UEAwwXb3BlbnZwbi1zZXJ2ZXIxLm9vbmkuaW8wHhcNMjQwNzI4MTE0\nOTIyWhcNMjYxMDMxMTE0OTIyWjAVMRMwEQYDVQQDDApDTElFTlROQU1FMIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0dHk7p78A4Cz/kNDdZWXF5v/kMQv\nXghZnslZij/4TN8vPZMFVdABXQDLGNm3+ycvJD3PUVmBU1SAJKC3tT6Y+rwiV9Kj\npJYDP4413CP67ZEgFd/JnuthyRnnjzkvB0VtaZ861s3hY06cZBKozqhB4PZSRK0t\nkefXLYN0uJqhVY//On1sVtzHH43zapZzkniHzljNgfqK68cwhn5LVq0B72/5hL8V\nKEYHf6WTZT/ph0pCH+5rtabLt6g+oH67XXLW6bWqgO+sgmWywHOg1nkrBhpplTUk\nGeVfH/sb4TC7syb4zEm7cEfSV2qyuSrOxh+1ATFjge6kgdUAqnXk7z7cYwIDAQAB\no4GuMIGrMAkGA1UdEwQCMAAwHQYDVR0OBBYEFLBzll2vqdxuZuys0G1In9uWmyo0\nMF0GA1UdIwRWMFSAFDob0DLA6BtSMNYP8N7BaewbVaiEoSakJDAiMSAwHgYDVQQD\nDBdvcGVudnBuLXNlcnZlcjEub29uaS5pb4IUVZz0MWBrsd26OIEccP08bNv+bScw\nEwYDVR0lBAwwCgYIKwYBBQUHAwIwCwYDVR0PBAQDAgeAMA0GCSqGSIb3DQEBCwUA\nA4IBAQADqxpvQ1GfmoXsioQZAMDjGe7OSVwLFX0JfYwfTE5b+41Ci1qNMN8MvnUE\nELPbiM4Ka5aJB4UyROml8lO8igqswqPFFSzj5MSzYJsS0oZO8RnCwOvIijxzxRjA\n/ND2tbl3HSv6h6O/9RHpqJrsqxaXIXWdtrpmwal8YNyTU1eQyh7fNnFbxwqy/6oO\n0AU3BjhDWC8GDZXrvzO5utIvE+aZmXQootiSA9AmdxfabaBs6gLKqAtip1wcVJq/\nzd//gBXi8Zu/2Narnxt1wen3wSYK/faA9qvHUtAfHxLNsFWKQiD6Cl+Ksdrj35yt\nRqTncboHHef0xRIvUleoOqQWPLnT\n-----END CERTIFICATE-----\n",
SafeKey: "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDR0eTunvwDgLP+\nQ0N1lZcXm/+QxC9eCFmeyVmKP/hM3y89kwVV0AFdAMsY2bf7Jy8kPc9RWYFTVIAk\noLe1Ppj6vCJX0qOklgM/jjXcI/rtkSAV38me62HJGeePOS8HRW1pnzrWzeFjTpxk\nEqjOqEHg9lJErS2R59ctg3S4mqFVj/86fWxW3McfjfNqlnOSeIfOWM2B+orrxzCG\nfktWrQHvb/mEvxUoRgd/pZNlP+mHSkIf7mu1psu3qD6gfrtdctbptaqA76yCZbLA\nc6DWeSsGGmmVNSQZ5V8f+xvhMLuzJvjMSbtwR9JXarK5Ks7GH7UBMWOB7qSB1QCq\ndeTvPtxjAgMBAAECggEBAJn1ky/JNxD26pxjDOgGCSVI0aGPY1ZzeBd8lZhNUkxN\n5GMhM2QBSk7NGzoz372JxhyowixmKfBUa+b0i3iR4zzwuZ6JsIw/i0iieED9oc2a\nlNmYKWDURR+EQ5ajli+WsS80qL8fuQfekgEYdAeYDSced8Vu8aZDYXBDKm2fAU0/\nFOnhhsGPOy6ojmYONnC6ny+thBaOIjNvxV87gvMds7NSfPZ4YkSkyHDe2c/qd/Wx\nq+A70zA1aONOeL/u2Vz0xugiPGqYgqkr4keooumUGtTiH8N7PmJKzQvB0ELc3XeA\nM+pWT2pG2B+ChcwpmpO0/XrZAOdQBdXre35mpqsIHsECgYEA8BHC96sIx0c5J45L\nD3FZpFjhR9ROqNuaUgPTWh2zO6gsOdfD0ENLkiLrkmpEbmg6A63itLPM7ekm+JIV\n/y39jyrg0miDRHcoZZTbBaoiDVTLapbi4o4LZcVp/XwIqm37HSZvNkD02RRFAbUc\nveajh8Dsozffr8wdGPL2BUY/rUMCgYEA375DFvTduK58IY9IMyHt80toZObGZ+W3\nKcHusWmFrnHyeVIwIetNZyJqyX1n204HbNx8EzApd7haJVojNCqn1oFVgmC+O2Rz\n1SUFp3w4AOSKtLZB7116UJ+n0AOipM19sYEkTKg+xN3saMymyshaAoEnVx9izLWr\nNNwWPsKakmECgYB1wwC0pP2FY3ax5KcFSEEE0WSQ66A6TJ8CpEXE6tTE6tXm+eRg\nAOLNKLwN8nrm/dGXhHC0244nFju7q02HA3RiClKGZCYgK6NxUPeva6mQiIvQGXvq\nTmtg3NoFMha+I30O64+aOXriEYNYNxOGQ+Dr8sMhvYLIpYOQfX4ZUEBkKQKBgQC1\n0b5hRGF9d8WF3BLXAoaEhE30WRj4S1OaCm+3GkI5LX3WmzRkC/wdiHlw/YjNTU55\nZ38odKXuFRCkc+hRtywnA3kCdy1/xDThC7HZlfdIunABRG62XqdMJ0HOp3WfKSIw\ngfqGlN5VSuaXj18nQMLscBoREX9PTX4weX1WSPwlYQKBgH7Ga1O5GEaRPDA8XCfW\nB5w1T9X8F9oSYWd8+VZVuxczCW3No68ENJGd1HJgkIp1bvoPT3XQEeYOb5ePyG3c\nR50Deu95AIsjS5U2cKGC2Aw3YyzGNPEkkGuCJqqsnT9nLc3+2lAntbXEkqdbOTfx\nWxxmiOcxGxbRFFuPOxxoXaEa\n-----END PRIVATE KEY-----\n",
}

0 comments on commit 209a238

Please sign in to comment.