package infra import ( "fmt" "strings" "time" ) // NordVPNContainerOpts opciones para el container gateway NordVPN. type NordVPNContainerOpts struct { Token string // Token de acceso NordVPN (obligatorio) Country string // Pais al que conectar (opcional, ej: "Spain") City string // Ciudad (opcional, ej: "Madrid") Protocol string // "NordLynx" o "OpenVPN" (default: NordLynx) Name string // Nombre del container (default: "nordvpn") } // NordVPNContainerStart levanta un container Docker con NordVPN como gateway. // Otros containers pueden usar su red con --network=container:. // Espera hasta que el tunel este activo o timeout de 30s. func NordVPNContainerStart(opts NordVPNContainerOpts) (string, error) { if opts.Token == "" { return "", fmt.Errorf("nordvpn token required") } if opts.Name == "" { opts.Name = "nordvpn" } if opts.Protocol == "" { opts.Protocol = "NordLynx" } env := map[string]string{ "TOKEN": opts.Token, "TECHNOLOGY": opts.Protocol, } if opts.Country != "" { connect := opts.Country if opts.City != "" { connect += " " + opts.City } env["CONNECT"] = connect } // Limpiar container previo con el mismo nombre si existe _ = DockerRemoveContainer(opts.Name, true) id, err := DockerRunContainer("ghcr.io/bubuntux/nordvpn", DockerRunOpts{ Name: opts.Name, Env: env, Detach: true, CapAdd: []string{"NET_ADMIN", "NET_RAW"}, }) if err != nil { return "", fmt.Errorf("nordvpn container start: %w", err) } // Esperar a que el tunel este activo for i := 0; i < 30; i++ { time.Sleep(1 * time.Second) lines, logErr := DockerContainerLogs(DockerLogsOpts{ ContainerID: opts.Name, Tail: 20, Stdout: true, Stderr: true, }) if logErr != nil { continue } var logText strings.Builder for _, l := range lines { logText.WriteString(l.Line) logText.WriteByte('\n') } logsStr := logText.String() if strings.Contains(logsStr, "Connected") || strings.Contains(logsStr, "connected") { return id, nil } if strings.Contains(logsStr, "error") || strings.Contains(logsStr, "failed") { return id, fmt.Errorf("nordvpn connection failed, check logs: docker logs %s", opts.Name) } } return id, fmt.Errorf("nordvpn connection timeout after 30s, check logs: docker logs %s", opts.Name) }