Files
hola-proxy/utils.go
2020-03-26 15:52:35 +02:00

138 lines
3.4 KiB
Go

package main
import (
"fmt"
"context"
"net"
"sync"
"io"
"os"
"time"
"encoding/base64"
"encoding/csv"
"errors"
"strings"
"strconv"
"net/http"
)
func basic_auth_header(login, password string) string {
return "basic " + base64.StdEncoding.EncodeToString(
[]byte(login + ":" + password))
}
func proxy(ctx context.Context, left, right net.Conn) {
wg := sync.WaitGroup{}
cpy := func (dst, src net.Conn) {
defer wg.Done()
io.Copy(dst, src)
dst.Close()
}
wg.Add(2)
go cpy(left, right)
go cpy(right, left)
groupdone := make(chan struct{})
go func() {
wg.Wait()
groupdone <-struct{}{}
}()
select {
case <-ctx.Done():
left.Close()
right.Close()
case <-groupdone:
return
}
<-groupdone
return
}
func print_countries(timeout time.Duration) int {
ctx, _ := context.WithTimeout(context.Background(), timeout)
countries, err := VPNCountries(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return 3
}
for _, code := range countries {
fmt.Printf("%v - %v\n", code, ISO3166[strings.ToUpper(code)])
}
return 0
}
func print_proxies(country string, limit uint, timeout time.Duration) int {
ctx, _ := context.WithTimeout(context.Background(), timeout)
tunnels, user_uuid, err := Tunnels(ctx, country, limit)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
return 3
}
wr := csv.NewWriter(os.Stdout)
login := LOGIN_PREFIX + user_uuid
password := tunnels.AgentKey
fmt.Println("Login:", login)
fmt.Println("Password:", password)
fmt.Println("Proxy-Authorization:",
basic_auth_header(login, password))
fmt.Println("")
wr.Write([]string{"Host", "IP address", "Direct port", "Peer port", "Vendor"})
for host, ip := range tunnels.IPList {
if (PROTOCOL_WHITELIST[tunnels.Protocol[host]]) {
wr.Write([]string{host,
ip,
strconv.FormatUint(uint64(tunnels.Port.Direct), 10),
strconv.FormatUint(uint64(tunnels.Port.Peer), 10),
tunnels.Vendor[host]})
}
}
wr.Flush()
return 0
}
func get_endpoint(tunnels *ZGetTunnelsResponse, typ string) (string, error) {
var hostname string
for k, _ := range tunnels.IPList {
hostname = k
break
}
if hostname == "" {
return "", errors.New("No tunnels found in API response")
}
var port uint16
if typ == "direct" {
port = tunnels.Port.Direct
} else if typ == "peer" {
port = tunnels.Port.Peer
} else {
return "", errors.New("Unsupported port type")
}
return net.JoinHostPort(hostname, strconv.FormatUint(uint64(port), 10)), nil
}
// Hop-by-hop headers. These are removed when sent to the backend.
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
var hopHeaders = []string{
"Connection",
"Keep-Alive",
"Proxy-Authenticate",
"Te", // canonicalized version of "TE"
"Trailers",
"Transfer-Encoding",
"Upgrade",
}
func copyHeader(dst, src http.Header) {
for k, vv := range src {
for _, v := range vv {
dst.Add(k, v)
}
}
}
func delHopHeaders(header http.Header) {
for _, h := range hopHeaders {
header.Del(h)
}
}