about summary refs log tree commit diff
path: root/src/access.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/access.go')
-rw-r--r--src/access.go90
1 files changed, 33 insertions, 57 deletions
diff --git a/src/access.go b/src/access.go
index 4ae96ed..6f0d848 100644
--- a/src/access.go
+++ b/src/access.go
@@ -16,13 +16,10 @@ import (
 )
 
 const(
-	vpnHostNetworkName = "vpnhostnet"
 	vpnContainerName = "circus-vpn"
 )
 
 var vpnContainerID string
-var vpnNetworkID string
-var vpnHostNetworkID string
 var remoteAddress* string
 var remotePort* int
 
@@ -32,24 +29,35 @@ func registerAccessFlags() {
 }
 
 func startVPN() (err error) {
+	// First: try to stop an existing container with that name, to avoid collision
+	// This container may exist if we didn't properly clean up on the last run, e.g. if the companion crashed.
+	stopVPN()
+	// stopVPN() as first command in startVPN()... This looks strange, but is perfectly fine ;)
+
 	// Set up our context and Docker CLI connection
 	setupContext()
 	setupDockerCLI()
-	// Set up network
-	err = setupNetwork()
 
-	if(err != nil) {
-		return err
+	// Set up VPN host network
+	if vpnHostNetworkID == "" {
+		id, err := setupNetwork(vpnHostNetworkName, false)
+		if (err != nil) {
+			return err
+		}
+		vpnHostNetworkID = id
 	}
 
-	err = setupVPNHostNetwork()
-
-	if err != nil {
-		return err
+	// Set up container network
+	if containerNetworkID == "" {
+		id, err := setupNetwork(containerNetworkName, true)
+		if (err != nil) {
+			return err
+		}
+		containerNetworkID = id
 	}
 
 	// Get subnet of challenge container network, to hand it over to our VPN container for routes
-	inspectResp, err := dockerCli.NetworkInspect(dockerCtx, vpnNetworkID, types.NetworkInspectOptions{})
+	inspectResp, err := dockerCli.NetworkInspect(dockerCtx, containerNetworkID, types.NetworkInspectOptions{})
 	if err != nil {
 		return err
 	}
@@ -95,7 +103,7 @@ func startVPN() (err error) {
 	}
 
 	// Attach container network to VPN container
-	err = dockerCli.NetworkConnect(dockerCtx, vpnNetworkID, resp.ID, &network.EndpointSettings{})
+	err = dockerCli.NetworkConnect(dockerCtx, containerNetworkID, resp.ID, &network.EndpointSettings{})
 	if err != nil {
 		return err
 	}
@@ -110,7 +118,7 @@ func startVPN() (err error) {
 	// However, getCertificate() requires that port 9999 of the VPN container hosts the configuration files for our client.
 	// That means we need to attach our own container - thanks to --privileged mode - into the VPN container network.
 	// We get the ID of our container from the "hostname" environment variable. That's a bit dirty, but works for the moment. TODO: solve this better.
-	err = dockerCli.NetworkConnect(dockerCtx, vpnNetworkID, os.Getenv("HOSTNAME"), &network.EndpointSettings{})
+	err = dockerCli.NetworkConnect(dockerCtx, vpnHostNetworkID, os.Getenv("HOSTNAME"), &network.EndpointSettings{})
 	if err != nil {
 		return err
 	}
@@ -130,44 +138,6 @@ func stopVPN() {
 	vpnContainerID = ""
 }
 
-func setupNetwork() (error) {
-	setupContext()
-	setupDockerCLI()
-
-	if vpnNetworkID == "" {
-		response, err := dockerCli.NetworkCreate(dockerCtx, VPNNetworkName, types.NetworkCreate{
-			Internal: true,
-		})
-
-		if err != nil {
-			return err
-		}
-
-		vpnNetworkID = response.ID
-	}
-
-	return nil
-}
-
-func setupVPNHostNetwork() (error) {
-	setupContext()
-	setupDockerCLI()
-
-	if vpnHostNetworkID == "" {
-		response, err := dockerCli.NetworkCreate(dockerCtx, vpnHostNetworkName, types.NetworkCreate{
-			Internal: false,
-		})
-
-		if err != nil {
-			return err
-		}
-
-		vpnHostNetworkID = response.ID
-	}
-
-	return nil
-}
-
 func getCertificate() (string, error) {
 	if vpnContainerID == "" {
 		return "", errors.New("VPN container not up")
@@ -182,16 +152,22 @@ func getCertificate() (string, error) {
 	// get certificate
 	var certResponse *http.Response
 
+	// retry for 10 seconds to dial to the VPN container
 	for i := 0; i < 10; i++ {
-		certResponse, err = http.Get(fmt.Sprintf("http://%s:9999/", inspectJSON.NetworkSettings.Networks[VPNNetworkName].IPAddress))
-
-		if err == nil {
-			break
+		// Check if the VPN container is already part of our challenge container network
+		if inspectJSON.NetworkSettings.Networks[vpnHostNetworkName] != nil {
+			// it is - get the IP address and dial to it
+			certResponse, err = http.Get(fmt.Sprintf("http://%s:9999/", inspectJSON.NetworkSettings.Networks[vpnHostNetworkName].IPAddress))
+
+			if err == nil {
+				break
+			}
 		}
+
 		time.Sleep(time.Second)
 	}
 
-	if err != nil {
+	if err != nil || certResponse == nil {
 		return "", err
 	}