master
fangdingjun 9 years ago
parent 179b61da8d
commit f0f0d1f88d

@ -1,104 +1,104 @@
package socks package socks
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"log" "log"
"net" "net"
) )
type socks4Conn struct { type socks4Conn struct {
server_conn net.Conn server_conn net.Conn
client_conn net.Conn client_conn net.Conn
} }
func (s4 *socks4Conn) Serve() { func (s4 *socks4Conn) Serve() {
defer s4.Close() defer s4.Close()
if err := s4.processRequest(); err != nil { if err := s4.processRequest(); err != nil {
log.Println(err) log.Println(err)
return return
} }
} }
func (s4 *socks4Conn) Close() { func (s4 *socks4Conn) Close() {
if s4.client_conn != nil { if s4.client_conn != nil {
s4.client_conn.Close() s4.client_conn.Close()
} }
if s4.server_conn != nil { if s4.server_conn != nil {
s4.server_conn.Close() s4.server_conn.Close()
} }
} }
func (s4 *socks4Conn) forward() { func (s4 *socks4Conn) forward() {
go func() { go func() {
io.Copy(s4.client_conn, s4.server_conn) io.Copy(s4.client_conn, s4.server_conn)
}() }()
io.Copy(s4.server_conn, s4.client_conn) io.Copy(s4.server_conn, s4.client_conn)
} }
func (s4 *socks4Conn) processRequest() error { func (s4 *socks4Conn) processRequest() error {
// version has already read out by socksConn.Serve() // version has already read out by socksConn.Serve()
// process command and target here // process command and target here
buf := make([]byte, 128) buf := make([]byte, 128)
n, err := io.ReadAtLeast(s4.client_conn, buf, 8) n, err := io.ReadAtLeast(s4.client_conn, buf, 8)
if err != nil { if err != nil {
return err return err
} }
// only support connect // only support connect
if buf[0] != cmdConnect { if buf[0] != cmdConnect {
return fmt.Errorf("error command %s", buf[0]) return fmt.Errorf("error command %s", buf[0])
} }
port := binary.BigEndian.Uint16(buf[1:3]) port := binary.BigEndian.Uint16(buf[1:3])
ip := net.IP(buf[3:7]) ip := net.IP(buf[3:7])
// NULL-terminated user string // NULL-terminated user string
// jump to NULL character // jump to NULL character
var j int var j int
for j = 7; j < n; j++ { for j = 7; j < n; j++ {
if buf[j] == 0x00 { if buf[j] == 0x00 {
break break
} }
} }
host := ip.String() host := ip.String()
// socks4a // socks4a
// 0.0.0.x // 0.0.0.x
if ip[0] == 0x00 && ip[1] == 0x00 && ip[2] == 0x00 && ip[3] != 0x00 { if ip[0] == 0x00 && ip[1] == 0x00 && ip[2] == 0x00 && ip[3] != 0x00 {
j++ j++
var i = j var i = j
// jump to the end of hostname // jump to the end of hostname
for j = i; j < n; j++ { for j = i; j < n; j++ {
if buf[j] == 0x00 { if buf[j] == 0x00 {
break break
} }
} }
host = string(buf[i:j]) host = string(buf[i:j])
} }
target := net.JoinHostPort(host, fmt.Sprintf("%d", port)) target := net.JoinHostPort(host, fmt.Sprintf("%d", port))
// reply user with connect success // reply user with connect success
// if dial to target failed, user will receive connection reset // if dial to target failed, user will receive connection reset
s4.client_conn.Write([]byte{0x00, 0x5a, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00}) s4.client_conn.Write([]byte{0x00, 0x5a, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00})
log.Printf("connecting to %s", target) log.Printf("connecting to %s", target)
// connect to the target // connect to the target
s4.server_conn, err = net.Dial("tcp", target) s4.server_conn, err = net.Dial("tcp", target)
if err != nil { if err != nil {
return err return err
} }
// enter data exchange // enter data exchange
s4.forward() s4.forward()
return nil return nil
} }

Loading…
Cancel
Save