Пример #1
0
// 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()
}
Пример #2
0
// 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())

	}
}
Пример #3
0
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
}
Пример #4
0
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()
				}
			}()
		}
	}
}
Пример #5
0
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")
}
Пример #6
0
// 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
	})
}
Пример #7
0
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
}
Пример #8
0
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
		}
	}
}
Пример #9
0
// 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
}
Пример #10
0
// 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()
}
Пример #11
0
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")
}
Пример #12
0
Файл: client.go Проект: pyr/warp
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
}
Пример #13
0
// 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)
	}
}
Пример #14
0
// 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)
}
Пример #15
0
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
}
Пример #17
0
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
		}
	}
}
Пример #18
0
// 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
}
Пример #19
0
// 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
}
Пример #20
0
// 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
}
Пример #21
0
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
}
Пример #22
0
// 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
}
Пример #23
0
/**
* 监听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
}
Пример #24
0
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
}
Пример #25
0
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
}
Пример #26
0
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)
}
Пример #27
0
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
}
Пример #28
0
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)
			}
		}
	}
}
Пример #29
0
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
		}
	}
}
Пример #30
0
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)
	}
}