X-Git-Url: http://www.git.cypherpunks.ru/?p=govpn.git;a=blobdiff_plain;f=src%2Fcypherpunks.ru%2Fgovpn%2Fcmd%2Fgovpn-client%2Fmain.go;h=df426ba8820c45bac23d84d83a21e814cf6e5540;hp=36ff72a113e6ac0db3e809e90af6954fb57f9f6c;hb=b69a57fb98ca6b03477487176021c2de053af5a7;hpb=0c1962bc188a553f95c2961922cec3fa937eeb98 diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go b/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go index 36ff72a..df426ba 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go @@ -23,46 +23,41 @@ import ( "flag" "fmt" "log" - "net" "os" "os/signal" "time" "cypherpunks.ru/govpn" -) - -var ( - remoteAddr = flag.String("remote", "", "Remote server address") - proto = flag.String("proto", "udp", "Protocol to use: udp or tcp") - ifaceName = flag.String("iface", "tap0", "TUN/TAP network interface") - verifierRaw = flag.String("verifier", "", "Verifier") - keyPath = flag.String("key", "", "Path to passphrase file") - upPath = flag.String("up", "", "Path to up-script") - downPath = flag.String("down", "", "Path to down-script") - stats = flag.String("stats", "", "Enable stats retrieving on host:port") - proxyAddr = flag.String("proxy", "", "Use HTTP proxy on host:port") - proxyAuth = flag.String("proxy-auth", "", "user:password Basic proxy auth") - mtu = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface") - timeoutP = flag.Int("timeout", 60, "Timeout seconds") - timeSync = flag.Int("timesync", 0, "Time synchronization requirement") - noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout") - noisy = flag.Bool("noise", false, "Enable noise appending") - encless = flag.Bool("encless", false, "Encryptionless mode") - cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate") - egdPath = flag.String("egd", "", "Optional path to EGD socket") - syslog = flag.Bool("syslog", false, "Enable logging to syslog") - version = flag.Bool("version", false, "Print version information") - warranty = flag.Bool("warranty", false, "Print warranty information") - - conf *govpn.PeerConf - tap *govpn.TAP - timeout int - firstUpCall bool = true - knownPeers govpn.KnownPeers - idsCache *govpn.MACCache + "cypherpunks.ru/govpn/client" ) func main() { + var ( + remoteAddr = flag.String("remote", "", "Remote server address") + proto = flag.String("proto", "udp", "Protocol to use: udp or tcp") + ifaceName = flag.String("iface", "tap0", "TUN/TAP network interface") + verifierRaw = flag.String("verifier", "", "Verifier") + keyPath = flag.String("key", "", "Path to passphrase file") + upPath = flag.String("up", "", "Path to up-script") + downPath = flag.String("down", "", "Path to down-script") + stats = flag.String("stats", "", "Enable stats retrieving on host:port") + proxyAddr = flag.String("proxy", "", "Use HTTP proxy on host:port") + proxyAuth = flag.String("proxy-auth", "", "user:password Basic proxy auth") + mtu = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface") + timeoutP = flag.Int("timeout", 60, "Timeout seconds") + timeSync = flag.Int("timesync", 0, "Time synchronization requirement") + noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout") + noisy = flag.Bool("noise", false, "Enable noise appending") + encless = flag.Bool("encless", false, "Encryptionless mode") + cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate") + egdPath = flag.String("egd", "", "Optional path to EGD socket") + syslog = flag.Bool("syslog", false, "Enable logging to syslog") + version = flag.Bool("version", false, "Print version information") + warranty = flag.Bool("warranty", false, "Print warranty information") + protocol client.Protocol + err error + ) + flag.Parse() if *warranty { fmt.Println(govpn.Warranty) @@ -72,72 +67,78 @@ func main() { fmt.Println(govpn.VersionGet()) return } - timeout = *timeoutP - var err error log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile) - if *mtu > govpn.MTUMax { - log.Fatalln("Maximum allowable MTU is", govpn.MTUMax) - } if *egdPath != "" { log.Println("Using", *egdPath, "EGD") govpn.EGDInit(*egdPath) } - if *proxyAddr != "" { - *proto = "tcp" - } - if !(*proto == "udp" || *proto == "tcp") { + switch *proto { + case "udp": + protocol = client.ProtocolUDP + case "tcp": + protocol = client.ProtocolTCP + default: log.Fatalln("Unknown protocol specified") } + + if *proxyAddr != "" && protocol == client.ProtocolUDP { + log.Println("Proxy is supported for TCP only, switch") + protocol = client.ProtocolTCP + } + if *verifierRaw == "" { - log.Fatalln("No verifier specified") + log.Fatalln("-verifier is required") } verifier, err := govpn.VerifierFromString(*verifierRaw) if err != nil { - log.Fatalln(err) + log.Fatalln("Invalid -verifier:", err) } key, err := govpn.KeyRead(*keyPath) if err != nil { - log.Fatalln("Unable to read the key", err) + log.Fatalln("Invalid -key:", err) } priv := verifier.PasswordApply(key) if *encless { - if *proto != "tcp" { + if protocol != client.ProtocolTCP { log.Fatalln("Currently encryptionless mode works only with TCP") } - *noisy = true + if !*noisy { + log.Println("-encless is on, force -noisy mode") + *noisy = true + } } - conf = &govpn.PeerConf{ - Id: verifier.Id, - Iface: *ifaceName, - MTU: *mtu, - Timeout: time.Second * time.Duration(timeout), - TimeSync: *timeSync, - Noise: *noisy, - CPR: *cpr, - Encless: *encless, - Verifier: verifier, - DSAPriv: priv, + conf := client.Configuration{ + PrivateKey: priv, + Peer: &govpn.PeerConf{ + Id: verifier.Id, + Iface: *ifaceName, + MTU: *mtu, + Timeout: time.Second * time.Duration(*timeoutP), + TimeSync: *timeSync, + Noise: *noisy, + CPR: *cpr, + Encless: *encless, + Verifier: verifier, + DSAPriv: priv, + }, + Protocol: protocol, + InterfaceName: *ifaceName, + ProxyAddress: *proxyAddr, + ProxyAuthentication: *proxyAuth, + RemoteAddress: *remoteAddr, + UpPath: *upPath, + DownPath: *downPath, + StatsAddress: *stats, + NoReconnect: *noreconnect, + MTU: *mtu, } - idsCache = govpn.NewMACCache() - confs := map[govpn.PeerId]*govpn.PeerConf{*verifier.Id: conf} - idsCache.Update(&confs) - log.Println(govpn.VersionGet()) - - tap, err = govpn.TAPListen(*ifaceName, *mtu) - if err != nil { - log.Fatalln("Can not listen on TUN/TAP interface:", err) + if err = conf.Validate(); err != nil { + log.Fatalln("Invalid settings:", err) } - if *stats != "" { - log.Println("Stats are going to listen on", *stats) - statsPort, err := net.Listen("tcp", *stats) - if err != nil { - log.Fatalln("Can not listen on stats port:", err) - } - go govpn.StatsProcessor(statsPort, &knownPeers) - } + log.Println(govpn.VersionGet()) if *syslog { govpn.SyslogEnable() @@ -145,38 +146,11 @@ func main() { termSignal := make(chan os.Signal, 1) signal.Notify(termSignal, os.Interrupt, os.Kill) - -MainCycle: - for { - timeouted := make(chan struct{}) - rehandshaking := make(chan struct{}) - termination := make(chan struct{}) - switch *proto { - case "udp": - go startUDP(timeouted, rehandshaking, termination) - case "tcp": - if *proxyAddr != "" { - go proxyTCP(timeouted, rehandshaking, termination) - } else { - go startTCP(timeouted, rehandshaking, termination) - } - } - select { - case <-termSignal: - govpn.BothPrintf(`[finish remote="%s"]`, *remoteAddr) - termination <- struct{}{} - break MainCycle - case <-timeouted: - if *noreconnect { - break MainCycle - } - govpn.BothPrintf(`[sleep seconds="%d"]`, timeout) - time.Sleep(time.Second * time.Duration(timeout)) - case <-rehandshaking: - } - close(timeouted) - close(rehandshaking) - close(termination) + c := client.NewClient(conf, verifier, termSignal) + go c.MainCycle() + if err := <-c.Error; err != nil { + log.Fatalln(err) + } else { + log.Println("Closed VPN tunnel") } - govpn.ScriptCall(*downPath, *ifaceName, *remoteAddr) }