gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

x_net_proxy.go (12907B)


      1 // Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
      2 //go:generate bundle -o x_net_proxy.go golang.org/x/net/proxy
      3 
      4 // Package proxy provides support for a variety of protocols to proxy network
      5 // data.
      6 //
      7 
      8 package websocket
      9 
     10 import (
     11 	"errors"
     12 	"io"
     13 	"net"
     14 	"net/url"
     15 	"os"
     16 	"strconv"
     17 	"strings"
     18 	"sync"
     19 )
     20 
     21 type proxy_direct struct{}
     22 
     23 // Direct is a direct proxy: one that makes network connections directly.
     24 var proxy_Direct = proxy_direct{}
     25 
     26 func (proxy_direct) Dial(network, addr string) (net.Conn, error) {
     27 	return net.Dial(network, addr)
     28 }
     29 
     30 // A PerHost directs connections to a default Dialer unless the host name
     31 // requested matches one of a number of exceptions.
     32 type proxy_PerHost struct {
     33 	def, bypass proxy_Dialer
     34 
     35 	bypassNetworks []*net.IPNet
     36 	bypassIPs      []net.IP
     37 	bypassZones    []string
     38 	bypassHosts    []string
     39 }
     40 
     41 // NewPerHost returns a PerHost Dialer that directs connections to either
     42 // defaultDialer or bypass, depending on whether the connection matches one of
     43 // the configured rules.
     44 func proxy_NewPerHost(defaultDialer, bypass proxy_Dialer) *proxy_PerHost {
     45 	return &proxy_PerHost{
     46 		def:    defaultDialer,
     47 		bypass: bypass,
     48 	}
     49 }
     50 
     51 // Dial connects to the address addr on the given network through either
     52 // defaultDialer or bypass.
     53 func (p *proxy_PerHost) Dial(network, addr string) (c net.Conn, err error) {
     54 	host, _, err := net.SplitHostPort(addr)
     55 	if err != nil {
     56 		return nil, err
     57 	}
     58 
     59 	return p.dialerForRequest(host).Dial(network, addr)
     60 }
     61 
     62 func (p *proxy_PerHost) dialerForRequest(host string) proxy_Dialer {
     63 	if ip := net.ParseIP(host); ip != nil {
     64 		for _, net := range p.bypassNetworks {
     65 			if net.Contains(ip) {
     66 				return p.bypass
     67 			}
     68 		}
     69 		for _, bypassIP := range p.bypassIPs {
     70 			if bypassIP.Equal(ip) {
     71 				return p.bypass
     72 			}
     73 		}
     74 		return p.def
     75 	}
     76 
     77 	for _, zone := range p.bypassZones {
     78 		if strings.HasSuffix(host, zone) {
     79 			return p.bypass
     80 		}
     81 		if host == zone[1:] {
     82 			// For a zone ".example.com", we match "example.com"
     83 			// too.
     84 			return p.bypass
     85 		}
     86 	}
     87 	for _, bypassHost := range p.bypassHosts {
     88 		if bypassHost == host {
     89 			return p.bypass
     90 		}
     91 	}
     92 	return p.def
     93 }
     94 
     95 // AddFromString parses a string that contains comma-separated values
     96 // specifying hosts that should use the bypass proxy. Each value is either an
     97 // IP address, a CIDR range, a zone (*.example.com) or a host name
     98 // (localhost). A best effort is made to parse the string and errors are
     99 // ignored.
    100 func (p *proxy_PerHost) AddFromString(s string) {
    101 	hosts := strings.Split(s, ",")
    102 	for _, host := range hosts {
    103 		host = strings.TrimSpace(host)
    104 		if len(host) == 0 {
    105 			continue
    106 		}
    107 		if strings.Contains(host, "/") {
    108 			// We assume that it's a CIDR address like 127.0.0.0/8
    109 			if _, net, err := net.ParseCIDR(host); err == nil {
    110 				p.AddNetwork(net)
    111 			}
    112 			continue
    113 		}
    114 		if ip := net.ParseIP(host); ip != nil {
    115 			p.AddIP(ip)
    116 			continue
    117 		}
    118 		if strings.HasPrefix(host, "*.") {
    119 			p.AddZone(host[1:])
    120 			continue
    121 		}
    122 		p.AddHost(host)
    123 	}
    124 }
    125 
    126 // AddIP specifies an IP address that will use the bypass proxy. Note that
    127 // this will only take effect if a literal IP address is dialed. A connection
    128 // to a named host will never match an IP.
    129 func (p *proxy_PerHost) AddIP(ip net.IP) {
    130 	p.bypassIPs = append(p.bypassIPs, ip)
    131 }
    132 
    133 // AddNetwork specifies an IP range that will use the bypass proxy. Note that
    134 // this will only take effect if a literal IP address is dialed. A connection
    135 // to a named host will never match.
    136 func (p *proxy_PerHost) AddNetwork(net *net.IPNet) {
    137 	p.bypassNetworks = append(p.bypassNetworks, net)
    138 }
    139 
    140 // AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
    141 // "example.com" matches "example.com" and all of its subdomains.
    142 func (p *proxy_PerHost) AddZone(zone string) {
    143 	if strings.HasSuffix(zone, ".") {
    144 		zone = zone[:len(zone)-1]
    145 	}
    146 	if !strings.HasPrefix(zone, ".") {
    147 		zone = "." + zone
    148 	}
    149 	p.bypassZones = append(p.bypassZones, zone)
    150 }
    151 
    152 // AddHost specifies a host name that will use the bypass proxy.
    153 func (p *proxy_PerHost) AddHost(host string) {
    154 	if strings.HasSuffix(host, ".") {
    155 		host = host[:len(host)-1]
    156 	}
    157 	p.bypassHosts = append(p.bypassHosts, host)
    158 }
    159 
    160 // A Dialer is a means to establish a connection.
    161 type proxy_Dialer interface {
    162 	// Dial connects to the given address via the proxy.
    163 	Dial(network, addr string) (c net.Conn, err error)
    164 }
    165 
    166 // Auth contains authentication parameters that specific Dialers may require.
    167 type proxy_Auth struct {
    168 	User, Password string
    169 }
    170 
    171 // FromEnvironment returns the dialer specified by the proxy related variables in
    172 // the environment.
    173 func proxy_FromEnvironment() proxy_Dialer {
    174 	allProxy := proxy_allProxyEnv.Get()
    175 	if len(allProxy) == 0 {
    176 		return proxy_Direct
    177 	}
    178 
    179 	proxyURL, err := url.Parse(allProxy)
    180 	if err != nil {
    181 		return proxy_Direct
    182 	}
    183 	proxy, err := proxy_FromURL(proxyURL, proxy_Direct)
    184 	if err != nil {
    185 		return proxy_Direct
    186 	}
    187 
    188 	noProxy := proxy_noProxyEnv.Get()
    189 	if len(noProxy) == 0 {
    190 		return proxy
    191 	}
    192 
    193 	perHost := proxy_NewPerHost(proxy, proxy_Direct)
    194 	perHost.AddFromString(noProxy)
    195 	return perHost
    196 }
    197 
    198 // proxySchemes is a map from URL schemes to a function that creates a Dialer
    199 // from a URL with such a scheme.
    200 var proxy_proxySchemes map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error)
    201 
    202 // RegisterDialerType takes a URL scheme and a function to generate Dialers from
    203 // a URL with that scheme and a forwarding Dialer. Registered schemes are used
    204 // by FromURL.
    205 func proxy_RegisterDialerType(scheme string, f func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) {
    206 	if proxy_proxySchemes == nil {
    207 		proxy_proxySchemes = make(map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error))
    208 	}
    209 	proxy_proxySchemes[scheme] = f
    210 }
    211 
    212 // FromURL returns a Dialer given a URL specification and an underlying
    213 // Dialer for it to make network requests.
    214 func proxy_FromURL(u *url.URL, forward proxy_Dialer) (proxy_Dialer, error) {
    215 	var auth *proxy_Auth
    216 	if u.User != nil {
    217 		auth = new(proxy_Auth)
    218 		auth.User = u.User.Username()
    219 		if p, ok := u.User.Password(); ok {
    220 			auth.Password = p
    221 		}
    222 	}
    223 
    224 	switch u.Scheme {
    225 	case "socks5":
    226 		return proxy_SOCKS5("tcp", u.Host, auth, forward)
    227 	}
    228 
    229 	// If the scheme doesn't match any of the built-in schemes, see if it
    230 	// was registered by another package.
    231 	if proxy_proxySchemes != nil {
    232 		if f, ok := proxy_proxySchemes[u.Scheme]; ok {
    233 			return f(u, forward)
    234 		}
    235 	}
    236 
    237 	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
    238 }
    239 
    240 var (
    241 	proxy_allProxyEnv = &proxy_envOnce{
    242 		names: []string{"ALL_PROXY", "all_proxy"},
    243 	}
    244 	proxy_noProxyEnv = &proxy_envOnce{
    245 		names: []string{"NO_PROXY", "no_proxy"},
    246 	}
    247 )
    248 
    249 // envOnce looks up an environment variable (optionally by multiple
    250 // names) once. It mitigates expensive lookups on some platforms
    251 // (e.g. Windows).
    252 // (Borrowed from net/http/transport.go)
    253 type proxy_envOnce struct {
    254 	names []string
    255 	once  sync.Once
    256 	val   string
    257 }
    258 
    259 func (e *proxy_envOnce) Get() string {
    260 	e.once.Do(e.init)
    261 	return e.val
    262 }
    263 
    264 func (e *proxy_envOnce) init() {
    265 	for _, n := range e.names {
    266 		e.val = os.Getenv(n)
    267 		if e.val != "" {
    268 			return
    269 		}
    270 	}
    271 }
    272 
    273 // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
    274 // with an optional username and password. See RFC 1928 and RFC 1929.
    275 func proxy_SOCKS5(network, addr string, auth *proxy_Auth, forward proxy_Dialer) (proxy_Dialer, error) {
    276 	s := &proxy_socks5{
    277 		network: network,
    278 		addr:    addr,
    279 		forward: forward,
    280 	}
    281 	if auth != nil {
    282 		s.user = auth.User
    283 		s.password = auth.Password
    284 	}
    285 
    286 	return s, nil
    287 }
    288 
    289 type proxy_socks5 struct {
    290 	user, password string
    291 	network, addr  string
    292 	forward        proxy_Dialer
    293 }
    294 
    295 const proxy_socks5Version = 5
    296 
    297 const (
    298 	proxy_socks5AuthNone     = 0
    299 	proxy_socks5AuthPassword = 2
    300 )
    301 
    302 const proxy_socks5Connect = 1
    303 
    304 const (
    305 	proxy_socks5IP4    = 1
    306 	proxy_socks5Domain = 3
    307 	proxy_socks5IP6    = 4
    308 )
    309 
    310 var proxy_socks5Errors = []string{
    311 	"",
    312 	"general failure",
    313 	"connection forbidden",
    314 	"network unreachable",
    315 	"host unreachable",
    316 	"connection refused",
    317 	"TTL expired",
    318 	"command not supported",
    319 	"address type not supported",
    320 }
    321 
    322 // Dial connects to the address addr on the given network via the SOCKS5 proxy.
    323 func (s *proxy_socks5) Dial(network, addr string) (net.Conn, error) {
    324 	switch network {
    325 	case "tcp", "tcp6", "tcp4":
    326 	default:
    327 		return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
    328 	}
    329 
    330 	conn, err := s.forward.Dial(s.network, s.addr)
    331 	if err != nil {
    332 		return nil, err
    333 	}
    334 	if err := s.connect(conn, addr); err != nil {
    335 		conn.Close()
    336 		return nil, err
    337 	}
    338 	return conn, nil
    339 }
    340 
    341 // connect takes an existing connection to a socks5 proxy server,
    342 // and commands the server to extend that connection to target,
    343 // which must be a canonical address with a host and port.
    344 func (s *proxy_socks5) connect(conn net.Conn, target string) error {
    345 	host, portStr, err := net.SplitHostPort(target)
    346 	if err != nil {
    347 		return err
    348 	}
    349 
    350 	port, err := strconv.Atoi(portStr)
    351 	if err != nil {
    352 		return errors.New("proxy: failed to parse port number: " + portStr)
    353 	}
    354 	if port < 1 || port > 0xffff {
    355 		return errors.New("proxy: port number out of range: " + portStr)
    356 	}
    357 
    358 	// the size here is just an estimate
    359 	buf := make([]byte, 0, 6+len(host))
    360 
    361 	buf = append(buf, proxy_socks5Version)
    362 	if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
    363 		buf = append(buf, 2 /* num auth methods */, proxy_socks5AuthNone, proxy_socks5AuthPassword)
    364 	} else {
    365 		buf = append(buf, 1 /* num auth methods */, proxy_socks5AuthNone)
    366 	}
    367 
    368 	if _, err := conn.Write(buf); err != nil {
    369 		return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
    370 	}
    371 
    372 	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
    373 		return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
    374 	}
    375 	if buf[0] != 5 {
    376 		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
    377 	}
    378 	if buf[1] == 0xff {
    379 		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
    380 	}
    381 
    382 	// See RFC 1929
    383 	if buf[1] == proxy_socks5AuthPassword {
    384 		buf = buf[:0]
    385 		buf = append(buf, 1 /* password protocol version */)
    386 		buf = append(buf, uint8(len(s.user)))
    387 		buf = append(buf, s.user...)
    388 		buf = append(buf, uint8(len(s.password)))
    389 		buf = append(buf, s.password...)
    390 
    391 		if _, err := conn.Write(buf); err != nil {
    392 			return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
    393 		}
    394 
    395 		if _, err := io.ReadFull(conn, buf[:2]); err != nil {
    396 			return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
    397 		}
    398 
    399 		if buf[1] != 0 {
    400 			return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
    401 		}
    402 	}
    403 
    404 	buf = buf[:0]
    405 	buf = append(buf, proxy_socks5Version, proxy_socks5Connect, 0 /* reserved */)
    406 
    407 	if ip := net.ParseIP(host); ip != nil {
    408 		if ip4 := ip.To4(); ip4 != nil {
    409 			buf = append(buf, proxy_socks5IP4)
    410 			ip = ip4
    411 		} else {
    412 			buf = append(buf, proxy_socks5IP6)
    413 		}
    414 		buf = append(buf, ip...)
    415 	} else {
    416 		if len(host) > 255 {
    417 			return errors.New("proxy: destination host name too long: " + host)
    418 		}
    419 		buf = append(buf, proxy_socks5Domain)
    420 		buf = append(buf, byte(len(host)))
    421 		buf = append(buf, host...)
    422 	}
    423 	buf = append(buf, byte(port>>8), byte(port))
    424 
    425 	if _, err := conn.Write(buf); err != nil {
    426 		return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
    427 	}
    428 
    429 	if _, err := io.ReadFull(conn, buf[:4]); err != nil {
    430 		return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
    431 	}
    432 
    433 	failure := "unknown error"
    434 	if int(buf[1]) < len(proxy_socks5Errors) {
    435 		failure = proxy_socks5Errors[buf[1]]
    436 	}
    437 
    438 	if len(failure) > 0 {
    439 		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
    440 	}
    441 
    442 	bytesToDiscard := 0
    443 	switch buf[3] {
    444 	case proxy_socks5IP4:
    445 		bytesToDiscard = net.IPv4len
    446 	case proxy_socks5IP6:
    447 		bytesToDiscard = net.IPv6len
    448 	case proxy_socks5Domain:
    449 		_, err := io.ReadFull(conn, buf[:1])
    450 		if err != nil {
    451 			return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
    452 		}
    453 		bytesToDiscard = int(buf[0])
    454 	default:
    455 		return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
    456 	}
    457 
    458 	if cap(buf) < bytesToDiscard {
    459 		buf = make([]byte, bytesToDiscard)
    460 	} else {
    461 		buf = buf[:bytesToDiscard]
    462 	}
    463 	if _, err := io.ReadFull(conn, buf); err != nil {
    464 		return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
    465 	}
    466 
    467 	// Also need to discard the port number
    468 	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
    469 		return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
    470 	}
    471 
    472 	return nil
    473 }