Skip to content
Snippets Groups Projects
Verified Commit 37413f5e authored by meskio's avatar meskio :tent:
Browse files

[feat] get openvpn args/gateways from the eip-service.json

parent d4f013fe
No related branches found
No related tags found
No related merge requests found
......@@ -18,13 +18,16 @@ package bitmask
import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
const (
certAPI = "https://api.black.riseup.net/1/cert"
eipAPI = "https://api.black.riseup.net/1/config/eip-service.json"
)
var (
......@@ -62,7 +65,33 @@ UN9SaWRlWKSdP4haujnzCoJbM7dU9bjvlGZNyXEekgeT0W2qFeGGp+yyUWw8tNsp
-----END CERTIFICATE-----`)
)
func getCertPem() ([]byte, error) {
type bonafide struct {
client *http.Client
eip *eipService
}
type eipService struct {
Gateways []gateway
Locations map[string]struct {
CountryCode string
Hemisphere string
Name string
Timezone string
}
OpenvpnConfiguration map[string]interface{} `json:"openvpn_configuration"`
}
type gateway struct {
Capabilities struct {
Ports []string
Protocols []string
}
Host string
IPAddress string `json:"ip_address"`
Location string
}
func newBonafide() *bonafide {
certs := x509.NewCertPool()
certs.AppendCertsFromPEM(caCert)
client := &http.Client{
......@@ -73,15 +102,74 @@ func getCertPem() ([]byte, error) {
},
}
resp, err := client.Post(certAPI, "", nil)
return &bonafide{client, nil}
}
func (b *bonafide) getCertPem() ([]byte, error) {
resp, err := b.client.Post(certAPI, "", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("get vpn cert has failed with status: %s", resp.Status)
}
return ioutil.ReadAll(resp.Body)
}
func (b *bonafide) getGateways() ([]gateway, error) {
if b.eip == nil {
err := b.fetchEipJSON()
if err != nil {
return nil, err
}
}
return b.eip.Gateways, nil
}
func (b *bonafide) getOpenvpnArgs() ([]string, error) {
if b.eip == nil {
err := b.fetchEipJSON()
if err != nil {
return nil, err
}
}
args := []string{}
for arg, value := range b.eip.OpenvpnConfiguration {
switch v := value.(type) {
case string:
args = append(args, "--"+arg, v)
case bool:
if v {
args = append(args, "--"+arg)
}
default:
log.Printf("Uknwon openvpn argument type: %s - %v", arg, value)
}
}
return args, nil
}
func (b *bonafide) fetchEipJSON() error {
resp, err := b.client.Post(eipAPI, "", nil)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("get vpn cert has failed with status: %s", resp.Status)
}
var eip eipService
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&eip)
if err != nil {
return err
}
b.eip = &eip
return nil
}
......@@ -11,16 +11,32 @@ var (
)
func TestGetCert(t *testing.T) {
cert, err := getCertPem()
b := newBonafide()
cert, err := b.getCertPem()
if err != nil {
t.Fatal("get_cert returned an error: ", err)
t.Fatal("getCert returned an error: ", err)
}
if !bytes.Contains(cert, privateKeyHeader) {
t.Errorf("No private key present: \n%q", cert)
}
if !bytes.Equal(cert, certHeader) {
if !bytes.Contains(cert, certHeader) {
t.Errorf("No cert present: \n%q", cert)
}
}
func TestGetGateways(t *testing.T) {
b := newBonafide()
gateways, err := b.getGateways()
if err != nil {
t.Fatal("getGateways returned an error: ", err)
}
for _, gw := range gateways {
if gw.IPAddress == "5.79.86.180" {
return
}
}
t.Errorf("5.79.86.180 not in the list")
}
......@@ -58,10 +58,12 @@ func (l *launcher) openvpnStop() error {
return runBitmaskRoot("openvpn", "stop")
}
func (l *launcher) firewallStart(gateways []string) error {
func (l *launcher) firewallStart(gateways []gateway) error {
log.Println("firewall start")
arg := []string{"firewall", "start"}
arg = append(arg, gateways...)
for _, gw := range gateways {
arg = append(arg, gw.IPAddress)
}
return runBitmaskRoot(arg...)
}
......
......@@ -28,6 +28,7 @@ type Bitmask struct {
tempdir string
statusCh chan string
managementClient *openvpn.MgmtClient
bonafide *bonafide
launch *launcher
}
......@@ -38,15 +39,16 @@ func Init() (*Bitmask, error) {
if err != nil {
return nil, err
}
bonafide := newBonafide()
launch := newLauncher()
b := Bitmask{tempdir, statusCh, nil, launch}
b := Bitmask{tempdir, statusCh, nil, bonafide, launch}
err = b.StopVPN()
if err != nil {
return nil, err
}
cert, err := getCertPem()
cert, err := b.bonafide.getCertPem()
if err != nil {
return nil, err
}
......
......@@ -24,26 +24,28 @@ const (
openvpnManagementPort = "6061"
)
var gateways = []string{
"5.79.86.180",
"199.58.81.145",
"198.252.153.28",
}
// StartVPN for provider
func (b *Bitmask) StartVPN(provider string) error {
// TODO: openvpn args are hardcoded
err := b.launch.firewallStart(gateways)
gateways, err := b.bonafide.getGateways()
if err != nil {
return err
}
err = b.launch.firewallStart(gateways)
if err != nil {
return err
}
arg := []string{"--nobind", "--verb", "1"}
bonafideArgs, err := b.bonafide.getOpenvpnArgs()
if err != nil {
return err
}
arg = append(arg, bonafideArgs...)
for _, gw := range gateways {
arg = append(arg, "--remote", gw, "443", "tcp4")
arg = append(arg, "--remote", gw.IPAddress, "443", "tcp4")
}
certPemPath := b.getCertPemPath()
arg = append(arg, "--client", "--tls-client", "--remote-cert-tls", "server", "--tls-cipher", "DHE-RSA-AES128-SHA", "--cipher", "AES-128-CBC", "--tun-ipv6", "--auth", "SHA1", "--keepalive", "10 30", "--management-client", "--management", openvpnManagementAddr+" "+openvpnManagementPort, "--ca", b.getCaCertPath(), "--cert", certPemPath, "--key", certPemPath)
arg = append(arg, "--client", "--tls-client", "--remote-cert-tls", "server", "--management-client", "--management", openvpnManagementAddr+" "+openvpnManagementPort, "--ca", b.getCaCertPath(), "--cert", certPemPath, "--key", certPemPath)
return b.launch.openvpnStart(arg...)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment