internal.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package dialer
  7. import (
  8. "net"
  9. "net/http"
  10. "net/url"
  11. "os"
  12. "time"
  13. "github.com/syncthing/syncthing/lib/util"
  14. "golang.org/x/net/proxy"
  15. )
  16. var (
  17. noFallback = os.Getenv("ALL_PROXY_NO_FALLBACK") != ""
  18. )
  19. func init() {
  20. proxy.RegisterDialerType("socks", socksDialerFunction)
  21. if proxyDialer := proxy.FromEnvironment(); proxyDialer != proxy.Direct {
  22. http.DefaultTransport = &http.Transport{
  23. DialContext: DialContext,
  24. Proxy: http.ProxyFromEnvironment,
  25. TLSHandshakeTimeout: 10 * time.Second,
  26. }
  27. // Defer this, so that logging gets setup.
  28. go func() {
  29. time.Sleep(500 * time.Millisecond)
  30. l.Infoln("Proxy settings detected")
  31. if noFallback {
  32. l.Infoln("Proxy fallback disabled")
  33. }
  34. }()
  35. } else {
  36. go func() {
  37. time.Sleep(500 * time.Millisecond)
  38. l.Debugln("Dialer logging disabled, as no proxy was detected")
  39. }()
  40. }
  41. }
  42. // This is a rip off of proxy.FromURL for "socks" URL scheme
  43. func socksDialerFunction(u *url.URL, forward proxy.Dialer) (proxy.Dialer, error) {
  44. var auth *proxy.Auth
  45. if u.User != nil {
  46. auth = new(proxy.Auth)
  47. auth.User = u.User.Username()
  48. if p, ok := u.User.Password(); ok {
  49. auth.Password = p
  50. }
  51. }
  52. return proxy.SOCKS5("tcp", u.Host, auth, forward)
  53. }
  54. // Sort available addresses, preferring unspecified address.
  55. func tcpAddrLess(i interface{}, j interface{}) bool {
  56. return util.AddressUnspecifiedLess(i.(*net.TCPAddr), j.(*net.TCPAddr))
  57. }
  58. // dialerConn is needed because proxy dialed connections have RemoteAddr() pointing at the proxy,
  59. // which then screws up various things such as IsLAN checks, and "let's populate the relay invitation address from
  60. // existing connection" shenanigans.
  61. type dialerConn struct {
  62. net.Conn
  63. addr net.Addr
  64. }
  65. func (c dialerConn) RemoteAddr() net.Addr {
  66. return c.addr
  67. }
  68. func newDialerAddr(network, addr string) net.Addr {
  69. netAddr, err := net.ResolveIPAddr(network, addr)
  70. if err == nil {
  71. return netAddr
  72. }
  73. return fallbackAddr{network, addr}
  74. }
  75. type fallbackAddr struct {
  76. network string
  77. addr string
  78. }
  79. func (a fallbackAddr) Network() string {
  80. return a.network
  81. }
  82. func (a fallbackAddr) String() string {
  83. return a.addr
  84. }