Source File
socks.go
Belonging Package
golang.org/x/net/internal/socks
package socks
import (
)
type AuthMethod int
type Reply int
func ( Reply) () string {
switch {
case StatusSucceeded:
return "succeeded"
case 0x01:
return "general SOCKS server failure"
case 0x02:
return "connection not allowed by ruleset"
case 0x03:
return "network unreachable"
case 0x04:
return "host unreachable"
case 0x05:
return "connection refused"
case 0x06:
return "TTL expired"
case 0x07:
return "command not supported"
case 0x08:
return "address type not supported"
default:
return "unknown code: " + strconv.Itoa(int())
}
}
const (
Version5 = 0x05
AddrTypeIPv4 = 0x01
AddrTypeFQDN = 0x03
AddrTypeIPv6 = 0x04
CmdConnect Command = 0x01 // establishes an active-open forward proxy connection
cmdBind Command = 0x02 // establishes a passive-open forward proxy connection
AuthMethodNotRequired AuthMethod = 0x00 // no authentication required
AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password
AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods
StatusSucceeded Reply = 0x00
)
type Dialer struct {
cmd Command // either CmdConnect or cmdBind
proxyNetwork string // network between a proxy server and a client
proxyAddress string // proxy server address
Authenticate func(context.Context, io.ReadWriter, AuthMethod) error
}
func ( *Dialer) ( context.Context, , string) (net.Conn, error) {
if := .validateTarget(, ); != nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
if == nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: errors.New("nil context")}
}
var error
var net.Conn
if .ProxyDial != nil {
, = .ProxyDial(, .proxyNetwork, .proxyAddress)
} else {
var net.Dialer
, = .DialContext(, .proxyNetwork, .proxyAddress)
}
if != nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
, := .connect(, , )
if != nil {
.Close()
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
return &Conn{Conn: , boundAddr: }, nil
}
func ( *Dialer) ( context.Context, net.Conn, , string) (net.Addr, error) {
if := .validateTarget(, ); != nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
if == nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: errors.New("nil context")}
}
, := .connect(, , )
if != nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
return , nil
}
func ( *Dialer) (, string) (net.Conn, error) {
if := .validateTarget(, ); != nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
var error
var net.Conn
if .ProxyDial != nil {
, = .ProxyDial(context.Background(), .proxyNetwork, .proxyAddress)
} else {
, = net.Dial(.proxyNetwork, .proxyAddress)
}
if != nil {
, , := .pathAddrs()
return nil, &net.OpError{Op: .cmd.String(), Net: , Source: , Addr: , Err: }
}
if , := .DialWithConn(context.Background(), , , ); != nil {
.Close()
return nil,
}
return , nil
}
func ( *Dialer) (, string) error {
switch {
case "tcp", "tcp6", "tcp4":
default:
return errors.New("network not implemented")
}
switch .cmd {
case CmdConnect, cmdBind:
default:
return errors.New("command not implemented")
}
return nil
}
func ( *Dialer) ( string) (, net.Addr, error) {
for , := range []string{.proxyAddress, } {
, , := splitHostPort()
if != nil {
return nil, nil,
}
:= &Addr{Port: }
.IP = net.ParseIP()
if .IP == nil {
.Name =
}
if == 0 {
=
} else {
=
}
}
return
}
func (, string) *Dialer {
return &Dialer{proxyNetwork: , proxyAddress: , cmd: CmdConnect}
}
const (
authUsernamePasswordVersion = 0x01
authStatusSucceeded = 0x00
)
type UsernamePassword struct {
Username string
Password string
}
func ( *UsernamePassword) ( context.Context, io.ReadWriter, AuthMethod) error {
switch {
case AuthMethodNotRequired:
return nil
case AuthMethodUsernamePassword:
if len(.Username) == 0 || len(.Username) > 255 || len(.Password) == 0 || len(.Password) > 255 {
return errors.New("invalid username/password")
}
:= []byte{authUsernamePasswordVersion}
= append(, byte(len(.Username)))
= append(, .Username...)
= append(, byte(len(.Password)))
if , := .Write(); != nil {
return
}
if , := io.ReadFull(, [:2]); != nil {
return
}
if [0] != authUsernamePasswordVersion {
return errors.New("invalid username/password version")
}
if [1] != authStatusSucceeded {
return errors.New("username/password authentication failed")
}
return nil
}
return errors.New("unsupported authentication method " + strconv.Itoa(int()))
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |