Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
txthinking committed Nov 5, 2016
1 parent 5bc732f commit 9a57ccf
Show file tree
Hide file tree
Showing 8 changed files with 594 additions and 0 deletions.
11 changes: 11 additions & 0 deletions auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package socks5

import (
"net"
)

const (
ERROR_USER_PASS_AUTH = errors.New("Invalid Username or Password for Auth")
)


Empty file added bind.go
Empty file.
165 changes: 165 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package socks5

import (
)

const (
ERROR_BAD_REPLY = errors.New("Bad Reply")
)

type Client struct{
}

func NewNegotiationRequest(methods []byte) *NegotiationRequest{
return &NegotiationRequest{
Ver: VER,
NMethods: len(methods),
Methods: methods,
}
}

func (r *NegotiationRequest) Write(w io.Writer) error{
if _, err := w.Write([]byte{r.Ver}); err != nil{
return err
}
if _, err := w.Write([]byte{r.NMethods}); err != nil{
return err
}
if _, err := w.Write(r.Methods); err != nil{
return err
}
return nil
}

func NewNegotiationReplyFrom(r io.Reader) (*NegotiationReply, error){
bb := make([]byte, 2)
if _, err := io.ReadFull(r, bb); err != nil {
return nil, err
}
if bb[0] != VER {
return nil, ERROR_VERSION
}
return &NegotiationReply{
Ver: bb[0],
Method: bb[1],
}, nil
}

func NewUserPassNegotiationRequest(username []byte, password []byte) *UserPassNegotiationRequest{
return &UserPassNegotiationRequest{
Ver: USER_PASS_VER,
Ulen: len(username),
Uname: username,
Plen: len(password),
Passwd: password,
}
}

func (r *UserPassNegotiationRequest) WriteTo(w io.Writer) error{
if _, err := w.Write([]byte{r.Ver, r.Ulen}); err != nil{
return err
}
if _, err := w.Write(r.Uname); err != nil{
return err
}
if _, err := w.Write([]byte{r.Plen}); err != nil{
return err
}
if _, err := w.Write(r.Passwd); err != nil{
return err
}
return nil
}

func NewUserPassNegotiationReplyFrom(r io.Reader) (*UserPassNegotiationReply, error){
bb := make([]byte, 2)
if _, err := io.ReadFull(r, bb); err != nil {
return nil, err
}
if bb[0] != USER_PASS_VER {
return nil, ERROR_USER_PASS_VERSION
}
return &UserPassNegotiationReply{
Ver: bb[0],
Status: bb[1],
}, nil
}


func NewRequest(cmd byte, atyp byte, addr []byte, port []byte) *Request{
return &Request{
Ver: VER,
Cmd: cmd,
Rsv: 0x00,
Atyp: atyp,
DstAddr: addr,
DstPort: port,
}
}

func (r *Request) WriteTo(w io.Writer) error{
if _, err := w.Write([]byte{r.Ver, r.Cmd, r.Rsv, r.Atyp}); err != nil{
return err
}
if r.Atyp == ATYP_DOMAIN {
if _, err := w.Write([]byte{len(r.DstAddr)}; err != nil{
return err
}
}
if _, err := w.Write(r.DstAddr); err != nil{
return err
}
if _, err := w.Write(r.DstPort); err != nil{
return err
}
return nil
}

func NewReplyFrom(r io.Reader) (*Reply, error){
bb := make([]byte, 4)
if _, err := io.ReadFull(r, bb); err != nil {
return nil, err
}
if bb[0] != VER {
return nil, ERROR_VERSION
}
var addr []byte
if bb[3] == ADPY_IPV4 {
addr = make([]byte, 4)
if _, err = io.ReadFull(r, addr); err != nil {
return nil, err
}
}else if bb[3] == ADPY_IPV6 {
addr = make([]byte, 16)
if _, err = io.ReadFull(r, addr); err != nil {
return nil, err
}
}else if bb[3] == ADPY_DOMAIN {
dal := make([]byte, 1)
if _, err = io.ReadFull(r, dal); err != nil {
return nil, err
}
if dal[0] == 0{
return nil, ERROR_BAD_REPLY
}
addr = make([]byte, int(dal[0]))
if _, err = io.ReadFull(r, addr); err != nil {
return nil, err
}
}else{
return nil, ERROR_BAD_REPLY
}
port := make([]byte, 2)
if _, err = io.ReadFull(r, port); err != nil {
return nil, err
}
return &Request{
Ver: bb[0],
Cmd: bb[1],
Rsv: bb[2],
Atyp: bb[3],
DstAddr: addr,
DstPort: port,
}, nil
}

37 changes: 37 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"net"
"log"
"time"

"github.com/txthinking/socks5"
)

func main(){
l, err := net.Listen("tcp", "1090")
if err != nil {
log.Fatal(err)
}
defer func() {
if err := l.Close(); err != nil {
log.Println(err)
}
}()
for{
c, err := l.Accept()
if err != nil {
log.Fatal(err)
}
if err := c.SetDeadline(time.Now().Add(10*time.Second)); err != nil {
log.Println(err)
if err = c.Close(); err != nil {
log.Println(err)
}
continue
}
s = socks5.NewServer(c)
go s.Handle()
}
}

22 changes: 22 additions & 0 deletions connect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package socks5

import (
)

func (r *Request) connect(c net.Conn) error {

rc, err := net.Dial("tcp", r.Address())
if err != nil {
p := NewReply(REP_HOST_UNREACHABLE, ATYP_IPV4, []byte{0,0,0,0}, []byte{0,0})
if err := p.WriteTo(s.c); err != nil {
log.Println(err)
}
}
ss := strings.Split(rc.LocalAddr().String(), ":")

p := NewReply(REP_SUCCESS, ATYP_IPV4, net.ParseIP(ss[0]), []byte{0,0})
if err := p.WriteTo(s.c); err != nil {
log.Println(err)
}
}

96 changes: 96 additions & 0 deletions handle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package socks5

import (
)

type Server struct{
c net.Conn
}

func NewServer(c net.Conn) *Server{
return &Server{
c: c,
}
}

func (s *Server) Handle() {
defer func() {
if err := s.c.Close(); err != nil {
log.Println(err)
}
}()

rq, err := NewNegotiationRequestFrom(s.c)
if err != nil {
log.Println(err)
return
}
var m byte
var got bool
for _, m = range rq.Methods {
if m == METHOD_NONE || m == METHOD_USERNAME_PASSWORD {
got = true
break
}
}
if !got {
rp := NewNegotiationReply(METHOD_UNSUPPORT_ALL)
if err := rp.WriteTo(s.c); err != nil {
log.Println(err)
}
return
}
rp := NewNegotiationReply(m)
if err := rp.WriteTo(s.c); err != nil {
log.Println(err)
return
}

if m == METHOD_USERNAME_PASSWORD {
urq, err := NewUserPassNegotiationRequestFrom(s.c)
if err != nil {
log.Println(err)
return
}
if urq.Uname != []byte("hello") || urq.Passwd != []byte("world") {
urp := NewUserPassNegotiationReply(USER_PASS_STATUS_FAILURE)
if err := urp.WriteTo(s.c); err != nil {
log.Println(err)
}
return
}
}

r, err := NewRequestFrom(s.c)
if err != nil {
log.Println(err)
return
}
if r.Cmd != CMD_CONNECT { // todo: need more work
p := NewReply(REP_COMMAND_NOT_SUPPORTED, ATYP_IPV4, []byte{0,0,0,0}, []byte{0,0})
if err := p.WriteTo(s.c); err != nil {
log.Println(err)
}
return
}

if r.Cmd == CMD_CONNECT {
if err := r.connect(s.c); err != nil{
log.Println(err)
}
return
}
if r.Cmd == CMD_BIND {
if err := r.bind(s.c); err != nil{
log.Println(err)
}
return
}
if r.Cmd == CMD_UDP {
if err := r.udp(s.c); err != nil{
log.Println(err)
}
return
}
}

Loading

0 comments on commit 9a57ccf

Please sign in to comment.