// Start the simple voice app on the encrypted channel. func startVoiceApp(tlsconn *tls.Conn, remoteCN string) { // start the speaker part and connect it to our socket spr := exec.Command("/usr/bin/aplay") spr.Stdin = tlsconn err := spr.Start() // start asynchronously check(err) // start the microphone too // defaults: 1 channel 8000 Hz sample rate, WAVE format mic := exec.Command("/usr/bin/arecord") mic.Stdout = tlsconn err = mic.Start() // start asynchronously check(err) // TODO: write a ping to signal connection // mess := text_to_speech("Connected to %s, chat away!\n", remoteCN) // spr.Write([]byte(mess)) // wait for it to finish // TODO: find a way to hang up the connection, short of killall arecord/aplay err = mic.Wait() check(err) err = spr.Wait() check(err) tlsconn.Close() }
// checkErr logs if an error occurs and closes the tlsConn. func checkErr(err error, tlsConn *tls.Conn) { if err != nil { tlsConn.Close() log.Fatalf("GBNetworkTools: %s\n", err.Error()) } }
func (d *relayDialer) Dial(id protocol.DeviceID, uri *url.URL) (IntermediateConnection, error) { inv, err := client.GetInvitationFromRelay(uri, id, d.tlsCfg.Certificates, 10*time.Second) if err != nil { return IntermediateConnection{}, err } conn, err := client.JoinSession(inv) if err != nil { return IntermediateConnection{}, err } err = dialer.SetTCPOptions(conn) if err != nil { conn.Close() return IntermediateConnection{}, err } var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, d.tlsCfg) } else { tc = tls.Client(conn, d.tlsCfg) } err = tc.Handshake() if err != nil { tc.Close() return IntermediateConnection{}, err } return IntermediateConnection{tc, "Relay (Client)", relayPriority}, nil }
func main() { ripmgr := randip.NewRandIPv4Mgr(true, 1249767200) for { newIP, err := ripmgr.GetNextIP() if err != nil { log.Println("IP Addr Exhausted") return } else { go func() { log.Println(newIP.String()) config := tls.Config{InsecureSkipVerify: true, ServerName: "google.com"} var err error var newConn *tls.Conn newConn, err = tls.DialWithDialer(&net.Dialer{Timeout: 2 * time.Second}, "tcp", newIP.String()+":443", &config) if err != nil { log.Println(err) } else { conState := newConn.ConnectionState() fmt.Println(newConn.RemoteAddr(), conState.PeerCertificates[0].NotBefore, conState.PeerCertificates[0].NotAfter, conState.PeerCertificates[0].SerialNumber) //jsonCert,_ := json.MarshalIndent(conState.PeerCertificates[0],""," ") //fmt.Println(string(jsonCert)) newConn.Close() } }() } } }
func closeAndCountFDs(t *testing.T, conn *tls.Conn, err error, fdStart int) { if err == nil { conn.Close() } fdEnd := countTCPFiles() assert.Equal(t, fdStart, fdEnd, "Number of open TCP files should be the same after test as before") }
// SessionResumeScan tests that host is able to resume sessions across all addresses. func sessionResumeScan(addr, hostname string) (grade Grade, output Output, err error) { config := defaultTLSConfig(hostname) config.ClientSessionCache = tls.NewLRUClientSessionCache(1) conn, err := tls.DialWithDialer(Dialer, Network, addr, config) if err != nil { return } if err = conn.Close(); err != nil { return } return multiscan(addr, func(addrport string) (g Grade, o Output, e error) { var conn *tls.Conn if conn, e = tls.DialWithDialer(Dialer, Network, addrport, config); e != nil { return } conn.Close() if o = conn.ConnectionState().DidResume; o.(bool) { g = Good } return }) }
func enrichWithOwnChecks(conn *tls.Conn, tlsConfig *tls.Config) error { var err error if err = conn.Handshake(); err != nil { conn.Close() return err } opts := x509.VerifyOptions{ Roots: tlsConfig.RootCAs, CurrentTime: time.Now(), DNSName: "", Intermediates: x509.NewCertPool(), } certs := conn.ConnectionState().PeerCertificates for i, cert := range certs { if i == 0 { continue } opts.Intermediates.AddCert(cert) } _, err = certs[0].Verify(opts) if err != nil { conn.Close() return err } return nil }
func (r *invitationReceiver) Serve() { for { select { case inv := <-r.invitations: l.Debugln("Received relay invitation", inv) conn, err := client.JoinSession(inv) if err != nil { l.Debugf("Failed to join relay session %s: %v", inv, err) continue } var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, r.tlsCfg) } else { tc = tls.Client(conn, r.tlsCfg) } err = tc.Handshake() if err != nil { l.Infof("TLS handshake (BEP/relay %s): %v", inv, err) tc.Close() continue } r.conns <- tc case <-r.stop: return } } }
// getChain returns chain of certificates retrieved from TLS session // established at given addr (host:port) for hostname provided. If addr is // empty, then hostname:443 is used. func getChain(hostname, addr string) ([]*x509.Certificate, error) { if hostname == "" { return nil, errors.New("empty hostname") } var ( conn *tls.Conn err error ) type tempErr interface { Temporary() bool } conf := &tls.Config{ServerName: hostname} if addr == "" { addr = hostname + ":443" } dialer := &net.Dialer{ Timeout: 30 * time.Second, } for i := 0; i < 3; i++ { if i > 0 { time.Sleep(time.Duration(i) * time.Second) } conn, err = tls.DialWithDialer(dialer, "tcp", addr, conf) if e, ok := err.(tempErr); ok && e.Temporary() { continue } if err != nil { return nil, err } defer conn.Close() return conn.ConnectionState().PeerCertificates, nil } return nil, err }
// Start the simple chat app on the encrypted channel. func startChatApp(tlsconn *tls.Conn, remoteCN string) { // Create listener socket for the simple chat socket, err := net.Listen("tcp", "[::1]:0") check(err) port := getPort(socket.Addr().String()) // start the chat app and point it to our socket cmd := exec.Command("uxterm", "-e", "nc", "-6", "::1", port) err = cmd.Start() // start asynchronously check(err) // wait for it to connect app, err := socket.Accept() check(err) // show a welcome message mess := fmt.Sprintf("Connected to %s, chat away!\n", remoteCN) app.Write([]byte(mess)) app.Write([]byte(fmt.Sprintf("%s\n", strings.Repeat("-", len(mess)-1)))) // copy the TLS-connection to the chat app and back go io.Copy(app, tlsconn) go io.Copy(tlsconn, app) // wait for it to finish err = cmd.Wait() check(err) // Close all, including the socket and the TLS channel. // We run this only once. app.Close() socket.Close() tlsconn.Close() }
func closeAndCountFDs(t *testing.T, conn *tls.Conn, err error, fdc *fdcount.Counter) { if err == nil { if err := conn.Close(); err != nil { t.Fatalf("Unable to close connection: %v", err) } } assert.NoError(t, fdc.AssertDelta(0), "Number of open TCP files should be the same after test as before") }
func ReadPacket(logger *log.Logger, conn *tls.Conn) (*Packet, error) { inbuf := make([]byte, 1024) br, err := conn.Read(inbuf) if err != nil { return nil, err } if br == 0 { return nil, errors.New("disconnected") } if br < 4 { return nil, errors.New("short read") } br = br - 4 phead := inbuf[0:4] b := bytes.NewReader(phead) var pilen uint32 err = binary.Read(b, binary.BigEndian, &pilen) plen := int(pilen) - 4 if err != nil { conn.Close() return nil, err } pdata := inbuf[4:] for { if br >= plen { break } buf := make([]byte, (plen - br)) nr, err := conn.Read(buf) if err != nil { conn.Close() return nil, err } if nr == 0 { return nil, err } pdata = append(pdata, buf...) br = br + nr } var p Packet err = json.Unmarshal(pdata[:plen], &p) if err != nil { return nil, err } return &p, nil }
// CheckVerification checks with the server that the user is verified, and exits the binary if it is not. func CheckVerification(tlsConn *tls.Conn, loginInfo, password string) { GBClientNetworkTools.WriteContentsToConn(tlsConn, "IS_ALREADY_VERIFIED", "1") GBClientNetworkTools.WriteContentsToConn(tlsConn, "USERNAME", loginInfo) GBClientNetworkTools.WriteContentsToConn(tlsConn, "PASSWORD", password) _, verified, _, err := GBClientNetworkTools.GetValueFromContentsBlock(tlsConn) checkErr(err, tlsConn) if verified != "true" { time.Sleep(1000 * time.Millisecond) tlsConn.Close() os.Exit(1) } }
// GracefullyExit is the default exit method for the binary. func GracefullyExit(tlsConn *tls.Conn, key []byte) { // Kill command to server err := GBClientNetworkTools.SendDataEncrypted(tlsConn, GBClientWatch.OutputData{"kill", true, 1, 1}, GBClientNetworkTools.DISCONNECT_CONST, key) if err != nil { fmt.Printf("Error: %s\n", err.Error()) } // Allow time to send request time.Sleep(200 * time.Millisecond) tlsConn.Close() os.Exit(1) }
func (p *httpProxyClient) DialTCPSAddr(network string, raddr string) (ProxyTCPConn, error) { var tlsConn *tls.Conn rawConn, err := p.upProxy.DialTCPSAddr(network, p.proxyAddr) if err != nil { return nil, fmt.Errorf("无法连接代理服务器 %v ,错误:%v", p.proxyAddr, err) } var c Conn = rawConn if p.proxyType == "https" { tlsConn = tls.Client(c, &tls.Config{ServerName: p.proxyDomain, InsecureSkipVerify: p.insecureSkipVerify}) if err := tlsConn.Handshake(); err != nil { tlsConn.Close() return nil, fmt.Errorf("TLS 协议握手错误:%v", err) } if p.insecureSkipVerify == false && tlsConn.VerifyHostname(p.proxyDomain) != nil { tlsConn.Close() return nil, fmt.Errorf("TLS 协议域名验证失败:%v", err) } c = tlsConn } req, err := http.NewRequest("CONNECT", p.proxyAddr, nil) if err != nil { c.Close() return nil, fmt.Errorf("创建请求错误:%v", err) } req.URL.Path = raddr req.URL.Host = p.proxyAddr if err := req.Write(c); err != nil { c.Close() return nil, fmt.Errorf("写请求错误:%v", err) } br := bufio.NewReader(c) res, err := http.ReadResponse(br, req) if err != nil { c.Close() return nil, fmt.Errorf("响应格式错误:%v", err) } if res.StatusCode != 200 { c.Close() return nil, fmt.Errorf("响应错误:%v", res) } return &HttpTCPConn{c, rawConn, tlsConn, net.TCPAddr{}, net.TCPAddr{}, "", "", 0, 0, p, res.Body}, nil }
func tryConnect(addr string, strict bool) (errchan chan error) { errchan = make(chan error) go func() { caCertFile, err := ioutil.TempFile("", "logstash-forwarder-cacert") if err != nil { panic(err) } defer func() { os.Remove(caCertFile.Name()) }() ioutil.WriteFile(caCertFile.Name(), []byte(caCert), os.ModeTemporary) // this can be messy because of localhost resolving to ipv6 addresses // but there's no easy way to disable v6 resolution here const wait = 5 const retryLimit = 3 tryAttempt := 0 exinfo := "" config := &NetworkConfig{ SSLCA: caCertFile.Name(), Servers: []string{addr}, Timeout: wait, timeout: time.Second * wait, } var socket *tls.Conn for socket == nil && tryAttempt < retryLimit { select { case socket = <-doConnect(config): case <-time.After(time.Second * wait): log.Printf("INFO: Connect timeout: attempt: %d\n", tryAttempt) tryAttempt++ } } if socket == nil { errchan <- errors.New("Client connect failed. " + exinfo) return } defer socket.Close() log.Printf("INFO: Connected to %s\n", socket.RemoteAddr()) if !socket.ConnectionState().HandshakeComplete { errchan <- errors.New("handshake should be complete") return } errchan <- nil }() return errchan }
func (r *invitationReceiver) Serve() { if r.stop != nil { return } r.stop = make(chan struct{}) for { select { case inv := <-r.invitations: if debug { l.Debugln("Received relay invitation", inv) } conn, err := client.JoinSession(inv) if err != nil { if debug { l.Debugf("Failed to join relay session %s: %v", inv, err) } continue } err = osutil.SetTCPOptions(conn.(*net.TCPConn)) if err != nil { l.Infoln(err) } var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, r.tlsCfg) } else { tc = tls.Client(conn, r.tlsCfg) } err = tc.Handshake() if err != nil { l.Infof("TLS handshake (BEP/relay %s): %v", inv, err) tc.Close() continue } r.conns <- model.IntermediateConnection{ tc, model.ConnectionTypeRelayAccept, } case <-r.stop: return } } }
// getChain is a helper function that retreives the host's certificate chain. func getChain(addr string, config *tls.Config) (chain []*x509.Certificate, err error) { var conn *tls.Conn conn, err = tls.DialWithDialer(Dialer, Network, addr, config) if err != nil { return } err = conn.Close() if err != nil { return } chain = conn.ConnectionState().PeerCertificates if len(chain) == 0 { err = fmt.Errorf("%s returned empty certificate chain", addr) } return }
// tlsDialScan tests that the host can perform a TLS Handshake // and warns if the server's certificate can't be verified. func tlsDialScan(addr, hostname string) (grade Grade, output Output, err error) { var conn *tls.Conn config := defaultTLSConfig(hostname) if conn, err = tls.DialWithDialer(Dialer, Network, addr, config); err != nil { return } conn.Close() config.InsecureSkipVerify = false if conn, err = tls.DialWithDialer(Dialer, Network, addr, config); err != nil { grade = Warning return } conn.Close() grade = Good return }
// Wrap a net.Conn into a client tls connection, performing any // additional verification as needed. // // As of go 1.3, crypto/tls only supports either doing no certificate // verification, or doing full verification including of the peer's // DNS name. For consul, we want to validate that the certificate is // signed by a known CA, but because consul doesn't use DNS names for // node names, we don't verify the certificate DNS names. Since go 1.3 // no longer supports this mode of operation, we have to do it // manually. func WrapTLSClient(conn net.Conn, tlsConfig *tls.Config) (net.Conn, error) { var err error var tlsConn *tls.Conn tlsConn = tls.Client(conn, tlsConfig) // If crypto/tls is doing verification, there's no need to do // our own. if tlsConfig.InsecureSkipVerify == false { return tlsConn, nil } if err = tlsConn.Handshake(); err != nil { tlsConn.Close() return nil, err } // The following is lightly-modified from the doFullHandshake // method in crypto/tls's handshake_client.go. opts := x509.VerifyOptions{ Roots: tlsConfig.RootCAs, CurrentTime: time.Now(), DNSName: "", Intermediates: x509.NewCertPool(), } certs := tlsConn.ConnectionState().PeerCertificates for i, cert := range certs { if i == 0 { continue } opts.Intermediates.AddCert(cert) } _, err = certs[0].Verify(opts) if err != nil { tlsConn.Close() return nil, err } return tlsConn, err }
func clientFunc(conn *tls.Conn) error { defer conn.Close() if !conn.ConnectionState().HandshakeComplete { return errors.New("handshake didn't complete") } input := []byte("Hello World!") if _, err := conn.Write(input); err != nil { return err } output, err := ioutil.ReadAll(conn) if err != nil { return err } if bytes.Compare(input, output) != 0 { return errors.New("input and output do not match") } return nil }
// ParseCertificateDomain parses the certificate served by the given domain. func ParseCertificateDomain(domain string) (cert *Certificate, err error) { var host, port string if host, port, err = net.SplitHostPort(domain); err != nil { host = domain port = "443" } var conn *tls.Conn conn, err = tls.DialWithDialer(&net.Dialer{Timeout: 10 * time.Second}, "tcp", net.JoinHostPort(host, port), &tls.Config{InsecureSkipVerify: true}) if err != nil { return } defer conn.Close() if len(conn.ConnectionState().PeerCertificates) == 0 { return nil, errors.New("received no server certificates") } cert = ParseCertificate(conn.ConnectionState().PeerCertificates[0]) return }
/** * 监听APNSSocket的返回结果,当有返回时,意味着发生错误了,这时把错误发到channel,同时关闭socket。 */ func monitorConn(conn *tls.Conn, app string, sandbox bool) { defer CapturePanic(fmt.Sprint("panic when monitor Connection %s", app)) defer conn.Close() reply := make([]byte, 6) n, err := conn.Read(reply) if err != nil && reply[0] != 8 { if strings.HasSuffix(err.Error(), "use of closed network connection") { log.Println("close the network connection") return } else { log.Printf("error when read from socket %s, %d", err, n) } } log.Printf("return %x, the id is %x", reply, reply[2:]) buf := bytes.NewBuffer(reply[2:]) var id int32 binary.Read(buf, binary.BigEndian, &id) rsp := &APNSRespone{reply[0], reply[1], id, conn, app, sandbox} responseCN <- rsp }
func (s *connectionSvc) connectViaRelay(deviceID protocol.DeviceID, addr discover.Relay) *tls.Conn { uri, err := url.Parse(addr.URL) if err != nil { l.Infoln("Failed to parse relay connection url:", addr, err) return nil } inv, err := client.GetInvitationFromRelay(uri, deviceID, s.tlsCfg.Certificates) if err != nil { l.Debugf("Failed to get invitation for %s from %s: %v", deviceID, uri, err) return nil } l.Debugln("Succesfully retrieved relay invitation", inv, "from", uri) conn, err := client.JoinSession(inv) if err != nil { l.Debugf("Failed to join relay session %s: %v", inv, err) return nil } l.Debugln("Successfully joined relay session", inv) var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, s.tlsCfg) } else { tc = tls.Client(conn, s.tlsCfg) } err = tc.Handshake() if err != nil { l.Infof("TLS handshake (BEP/relay %s): %v", inv, err) tc.Close() return nil } return tc }
func dialTLSWithOwnChecks(config *caretakerd.Config, tlsConfig *tls.Config) (net.Conn, error) { var err error var tlsConn *tls.Conn address := config.RPC.Listen tlsConn, err = tls.Dial(address.AsScheme(), address.AsAddress(), tlsConfig) if err != nil { return nil, err } if err = tlsConn.Handshake(); err != nil { tlsConn.Close() return nil, err } opts := x509.VerifyOptions{ Roots: tlsConfig.RootCAs, CurrentTime: time.Now(), DNSName: "", Intermediates: x509.NewCertPool(), } certs := tlsConn.ConnectionState().PeerCertificates for i, cert := range certs { if i == 0 { continue } opts.Intermediates.AddCert(cert) } _, err = certs[0].Verify(opts) if err != nil { tlsConn.Close() return nil, err } return tlsConn, err }
func testRoundTrip(t *testing.T, proxy *server.Server, origin *originHandler, checkerFn func(conn net.Conn, proxy *server.Server, originURL *url.URL)) { var conn net.Conn var err error addr := proxy.Addr.String() if !proxy.Tls { conn, err = net.Dial("tcp", addr) log.Debugf("%s -> %s (via HTTP) -> %s", conn.LocalAddr().String(), addr, origin.server.URL) if !assert.NoError(t, err, "should dial proxy server") { t.FailNow() } } else { var tlsConn *tls.Conn x509cert := serverCertificate.X509() tlsConn, err = tls.Dial("tcp", addr, &tls.Config{ CipherSuites: preferredCipherSuites, InsecureSkipVerify: true, }) log.Debugf("%s -> %s (via HTTPS) -> %s", tlsConn.LocalAddr().String(), addr, origin.server.URL) if !assert.NoError(t, err, "should dial proxy server") { t.FailNow() } conn = tlsConn if !tlsConn.ConnectionState().PeerCertificates[0].Equal(x509cert) { if err := tlsConn.Close(); err != nil { log.Errorf("Error closing chained server connection: %s", err) } t.Fatal("Server's certificate didn't match expected") } } defer func() { assert.NoError(t, conn.Close(), "should close connection") }() url, _ := url.Parse(origin.server.URL) checkerFn(conn, proxy, url) }
func (d *relayDialer) Dial(id protocol.DeviceID, uri *url.URL) (internalConn, error) { inv, err := client.GetInvitationFromRelay(uri, id, d.tlsCfg.Certificates, 10*time.Second) if err != nil { return internalConn{}, err } conn, err := client.JoinSession(inv) if err != nil { return internalConn{}, err } err = dialer.SetTCPOptions(conn) if err != nil { conn.Close() return internalConn{}, err } err = dialer.SetTrafficClass(conn, d.cfg.Options().TrafficClass) if err != nil { l.Debugf("failed to set traffic class: %s", err) } var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, d.tlsCfg) } else { tc = tls.Client(conn, d.tlsCfg) } err = tlsTimedHandshake(tc) if err != nil { tc.Close() return internalConn{}, err } return internalConn{tc, connTypeRelayClient, relayPriority}, nil }
func (t *relayListener) Serve() { t.mut.Lock() t.err = nil t.mut.Unlock() clnt, err := client.NewClient(t.uri, t.tlsCfg.Certificates, nil, 10*time.Second) if err != nil { t.mut.Lock() t.err = err t.mut.Unlock() l.Warnln("listen (BEP/relay):", err) return } go clnt.Serve() t.mut.Lock() t.client = clnt t.mut.Unlock() oldURI := clnt.URI() for { select { case inv, ok := <-t.client.Invitations(): if !ok { return } conn, err := client.JoinSession(inv) if err != nil { l.Warnln("Joining relay session (BEP/relay):", err) continue } err = dialer.SetTCPOptions(conn.(*net.TCPConn)) if err != nil { l.Infoln(err) } var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, t.tlsCfg) } else { tc = tls.Client(conn, t.tlsCfg) } err = tc.Handshake() if err != nil { tc.Close() l.Infoln("TLS handshake (BEP/relay):", err) continue } t.conns <- IntermediateConnection{tc, "Relay (Server)", relayPriority} // Poor mans notifier that informs the connection service that the // relay URI has changed. This can only happen when we connect to a // relay via dynamic+http(s) pool, which upon a relay failing/dropping // us, would pick a different one. case <-time.After(10 * time.Second): currentURI := clnt.URI() if currentURI != oldURI { oldURI = currentURI t.notifyAddressesChanged(t) } } } }
func (s *connectionSvc) connect() { delay := time.Second for { nextDevice: for deviceID, deviceCfg := range s.cfg.Devices() { if deviceID == myID { continue } if s.model.IsPaused(deviceID) { continue } connected := s.model.ConnectedTo(deviceID) s.mut.RLock() ct, ok := s.connType[deviceID] relaysEnabled := s.relaysEnabled s.mut.RUnlock() if connected && ok && ct.IsDirect() { continue } var addrs []string var relays []discover.Relay for _, addr := range deviceCfg.Addresses { if addr == "dynamic" { if s.discoverer != nil { if t, r, err := s.discoverer.Lookup(deviceID); err == nil { addrs = append(addrs, t...) relays = append(relays, r...) } } } else { addrs = append(addrs, addr) } } for _, addr := range addrs { uri, err := url.Parse(addr) if err != nil { l.Infoln("Failed to parse connection url:", addr, err) continue } dialer, ok := dialers[uri.Scheme] if !ok { l.Infoln("Unknown address schema", uri.String()) continue } if debugNet { l.Debugln("dial", deviceCfg.DeviceID, uri.String()) } conn, err := dialer(uri, s.tlsCfg) if err != nil { if debugNet { l.Debugln("dial failed", deviceCfg.DeviceID, uri.String(), err) } continue } if connected { s.model.Close(deviceID, fmt.Errorf("switching connections")) } s.conns <- model.IntermediateConnection{ conn, model.ConnectionTypeDirectDial, } continue nextDevice } // Only connect via relays if not already connected // Also, do not set lastRelayCheck time if we have no relays, // as otherwise when we do discover relays, we might have to // wait up to RelayReconnectIntervalM to connect again. // Also, do not try relays if we are explicitly told not to. if connected || len(relays) == 0 || !relaysEnabled { continue nextDevice } reconIntv := time.Duration(s.cfg.Options().RelayReconnectIntervalM) * time.Minute if last, ok := s.lastRelayCheck[deviceID]; ok && time.Since(last) < reconIntv { if debugNet { l.Debugln("Skipping connecting via relay to", deviceID, "last checked at", last) } continue nextDevice } else if debugNet { l.Debugln("Trying relay connections to", deviceID, relays) } s.lastRelayCheck[deviceID] = time.Now() for _, addr := range relays { uri, err := url.Parse(addr.URL) if err != nil { l.Infoln("Failed to parse relay connection url:", addr, err) continue } inv, err := client.GetInvitationFromRelay(uri, deviceID, s.tlsCfg.Certificates) if err != nil { if debugNet { l.Debugf("Failed to get invitation for %s from %s: %v", deviceID, uri, err) } continue } else if debugNet { l.Debugln("Succesfully retrieved relay invitation", inv, "from", uri) } conn, err := client.JoinSession(inv) if err != nil { if debugNet { l.Debugf("Failed to join relay session %s: %v", inv, err) } continue } else if debugNet { l.Debugln("Sucessfully joined relay session", inv) } err = osutil.SetTCPOptions(conn.(*net.TCPConn)) if err != nil { l.Infoln(err) } var tc *tls.Conn if inv.ServerSocket { tc = tls.Server(conn, s.tlsCfg) } else { tc = tls.Client(conn, s.tlsCfg) } err = tc.Handshake() if err != nil { l.Infof("TLS handshake (BEP/relay %s): %v", inv, err) tc.Close() continue } s.conns <- model.IntermediateConnection{ tc, model.ConnectionTypeRelayDial, } continue nextDevice } } time.Sleep(delay) delay *= 2 if maxD := time.Duration(s.cfg.Options().ReconnectIntervalS) * time.Second; delay > maxD { delay = maxD } } }
func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) dialer, _ := utilnet.Dialer(transport) switch url.Scheme { case "http": if dialer != nil { return dialer("tcp", dialAddr) } return net.Dial("tcp", dialAddr) case "https": // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config var tlsConn *tls.Conn var err error tlsConfig, _ = utilnet.TLSClientConfig(transport) if dialer != nil { // We have a dialer; use it to open the connection, then // create a tls client using the connection. netConn, err := dialer("tcp", dialAddr) if err != nil { return nil, err } if tlsConfig == nil { // tls.Client requires non-nil config glog.Warningf("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify") // tls.Handshake() requires ServerName or InsecureSkipVerify tlsConfig = &tls.Config{ InsecureSkipVerify: true, } } else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify { // tls.Handshake() requires ServerName or InsecureSkipVerify // infer the ServerName from the hostname we're connecting to. inferredHost := dialAddr if host, _, err := net.SplitHostPort(dialAddr); err == nil { inferredHost = host } // Make a copy to avoid polluting the provided config tlsConfigCopy := *tlsConfig tlsConfigCopy.ServerName = inferredHost tlsConfig = &tlsConfigCopy } tlsConn = tls.Client(netConn, tlsConfig) if err := tlsConn.Handshake(); err != nil { netConn.Close() return nil, err } } else { // Dial tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err } } // Return if we were configured to skip validation if tlsConfig != nil && tlsConfig.InsecureSkipVerify { return tlsConn, nil } // Verify host, _, _ := net.SplitHostPort(dialAddr) if err := tlsConn.VerifyHostname(host); err != nil { tlsConn.Close() return nil, err } return tlsConn, nil default: return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme) } }