Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
G
gost
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
gost
Commits
822cc6ac
Commit
822cc6ac
authored
Jul 18, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
9884015d
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
164 additions
and
369 deletions
+164
-369
handler.go
handler.go
+26
-0
options.go
options.go
+11
-3
ss.go
ss.go
+92
-159
ssocks/ssocks.go
ssocks/ssocks.go
+0
-165
tcp/client.go
tcp/client.go
+12
-9
tcp/options.go
tcp/options.go
+4
-15
tcp/server.go
tcp/server.go
+19
-18
No files found.
handler.go
0 → 100644
View file @
822cc6ac
package
gost
import
(
"net"
)
type
Handler
interface
{
Handle
(
net
.
Conn
)
}
type
DefaultHandler
struct
{
server
Server
}
func
(
h
*
DefaultHandler
)
Handle
(
conn
net
.
Conn
)
{
var
handler
Handler
switch
h
.
server
.
Options
()
.
BaseOptions
()
.
Protocol
{
case
"http"
:
case
"ss"
:
// shadowsocks
handler
=
ShadowHandler
(
h
.
server
)
}
handler
.
Handle
(
conn
)
}
options.go
View file @
822cc6ac
...
@@ -2,6 +2,7 @@ package gost
...
@@ -2,6 +2,7 @@ package gost
import
(
import
(
"log"
"log"
"net/url"
"reflect"
"reflect"
)
)
...
@@ -16,6 +17,7 @@ type BaseOptions struct {
...
@@ -16,6 +17,7 @@ type BaseOptions struct {
Addr
string
`opt:"addr"`
// [host]:port
Addr
string
`opt:"addr"`
// [host]:port
Protocol
string
`opt:"protocol"`
// protocol: http/socks5/ss
Protocol
string
`opt:"protocol"`
// protocol: http/socks5/ss
Transport
string
`opt:"transport"`
// transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp
Transport
string
`opt:"transport"`
// transport: ws/wss/tls/http2/tcp/udp/rtcp/rudp
Users
[]
url
.
Userinfo
`opt:"users"`
// authentication for proxy
}
}
func
AddrOption
(
a
string
)
Option
{
func
AddrOption
(
a
string
)
Option
{
...
@@ -36,6 +38,12 @@ func TransportOption(t string) Option {
...
@@ -36,6 +38,12 @@ func TransportOption(t string) Option {
}
}
}
}
func
UsersOption
(
users
...
url
.
Userinfo
)
Option
{
return
func
(
opts
Options
)
{
opts
.
BaseOptions
()
.
Users
=
users
}
}
func
GetOption
(
i
interface
{},
opt
string
)
interface
{}
{
func
GetOption
(
i
interface
{},
opt
string
)
interface
{}
{
ps
:=
reflect
.
ValueOf
(
i
)
ps
:=
reflect
.
ValueOf
(
i
)
if
ps
.
Kind
()
!=
reflect
.
Ptr
&&
ps
.
Kind
()
!=
reflect
.
Interface
{
if
ps
.
Kind
()
!=
reflect
.
Ptr
&&
ps
.
Kind
()
!=
reflect
.
Interface
{
...
...
ss.go
View file @
822cc6ac
...
@@ -3,7 +3,6 @@ package gost
...
@@ -3,7 +3,6 @@ package gost
import
(
import
(
"bytes"
"bytes"
"encoding/binary"
"encoding/binary"
"errors"
"fmt"
"fmt"
"io"
"io"
"net"
"net"
...
@@ -11,72 +10,126 @@ import (
...
@@ -11,72 +10,126 @@ import (
"time"
"time"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gosocks5"
"github.com/go-log/log"
"github.com/golang/glog"
"github.com/golang/glog"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
)
)
const
(
// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
idType
=
0
// address type index
// we wrap around it to make io.Copy happy
idIP0
=
1
// ip addres start index
type
shadowConn
struct
{
idDmLen
=
1
// domain address length index
conn
net
.
Conn
idDm0
=
2
// domain address start index
}
typeIPv4
=
1
// type is ipv4 address
func
ShadowConn
(
conn
net
.
Conn
)
net
.
Conn
{
typeDm
=
3
// type is domain address
return
&
shadowConn
{
conn
:
conn
}
typeIPv6
=
4
// type is ipv6 address
}
lenIPv4
=
net
.
IPv4len
+
2
// ipv4 + 2port
func
(
c
*
shadowConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
lenIPv6
=
net
.
IPv6len
+
2
// ipv6 + 2port
return
c
.
conn
.
Read
(
b
)
lenDmBase
=
2
// 1addrLen + 2port, plus addrLen
}
lenHmacSha1
=
10
)
type
ShadowServer
struct
{
func
(
c
*
shadowConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
conn
*
ss
.
Conn
n
=
len
(
b
)
// force byte length consistent
Base
*
ProxyServer
_
,
err
=
c
.
conn
.
Write
(
b
)
OTA
bool
// one time auth
return
}
func
(
c
*
shadowConn
)
Close
()
error
{
return
c
.
conn
.
Close
()
}
}
func
NewShadowServer
(
conn
*
ss
.
Conn
,
base
*
ProxyServer
)
*
ShadowServe
r
{
func
(
c
*
shadowConn
)
LocalAddr
()
net
.
Add
r
{
return
&
ShadowServer
{
conn
:
conn
,
Base
:
base
}
return
c
.
conn
.
LocalAddr
()
}
}
func
(
s
*
ShadowServer
)
Serve
()
{
func
(
c
*
shadowConn
)
RemoteAddr
()
net
.
Addr
{
glog
.
V
(
LINFO
)
.
Infof
(
"[ss] %s - %s"
,
s
.
conn
.
RemoteAddr
(),
s
.
conn
.
LocalAddr
())
return
c
.
conn
.
RemoteAddr
()
}
addr
,
ota
,
err
:=
s
.
getRequest
()
func
(
c
*
shadowConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetDeadline
(
t
)
}
func
(
c
*
shadowConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetReadDeadline
(
t
)
}
func
(
c
*
shadowConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
type
shadowHandler
struct
{
server
Server
}
func
ShadowHandler
(
server
Server
)
Handler
{
return
&
shadowHandler
{
server
:
server
}
}
func
(
h
*
shadowHandler
)
Handle
(
conn
net
.
Conn
)
{
var
method
,
password
string
users
:=
h
.
server
.
Options
()
.
BaseOptions
()
.
Users
if
len
(
users
)
>
0
{
method
=
users
[
0
]
.
Username
()
password
,
_
=
users
[
0
]
.
Password
()
}
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ss] %s - %s : %s"
,
s
.
conn
.
RemoteAddr
(),
s
.
conn
.
LocalAddr
()
,
err
)
log
.
Log
(
"[ss]"
,
err
)
return
return
}
}
glog
.
V
(
LINFO
)
.
Infof
(
"[ss] %s -> %s, ota: %v"
,
s
.
conn
.
RemoteAddr
(),
addr
,
ota
)
conn
=
ShadowConn
(
ss
.
NewConn
(
conn
,
cipher
)
)
cc
,
err
:=
s
.
Base
.
Chain
.
Dial
(
addr
)
log
.
Logf
(
"[ss] %s - %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
addr
,
err
:=
h
.
getRequest
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ss] %s -> %s : %s"
,
s
.
conn
.
RemoteAddr
(),
addr
,
err
)
log
.
Logf
(
"[ss] %s - %s : %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
()
,
err
)
return
return
}
}
defer
cc
.
Close
(
)
log
.
Logf
(
"[ss] %s -> %s"
,
conn
.
RemoteAddr
(),
addr
)
glog
.
V
(
LINFO
)
.
Infof
(
"[ss] %s <-> %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
cc
,
err
:=
h
.
server
.
Chain
()
.
Dial
(
addr
)
if
ota
{
if
err
!=
nil
{
s
.
transportOTA
(
s
.
conn
,
cc
)
log
.
Logf
(
"[ss] %s -> %s : %s"
,
conn
.
RemoteAddr
(),
addr
,
err
)
}
else
{
return
s
.
Base
.
transport
(
&
shadowConn
{
conn
:
s
.
conn
},
cc
)
}
}
glog
.
V
(
LINFO
)
.
Infof
(
"[ss] %s >-< %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
defer
cc
.
Close
()
log
.
Logf
(
"[ss] %s <-> %s"
,
conn
.
RemoteAddr
(),
addr
)
defer
log
.
Logf
(
"[ss] %s >-< %s"
,
conn
.
RemoteAddr
(),
addr
)
Transport
(
conn
,
cc
)
}
}
const
(
idType
=
0
// address type index
idIP0
=
1
// ip addres start index
idDmLen
=
1
// domain address length index
idDm0
=
2
// domain address start index
typeIPv4
=
1
// type is ipv4 address
typeDm
=
3
// type is domain address
typeIPv6
=
4
// type is ipv6 address
lenIPv4
=
net
.
IPv4len
+
2
// ipv4 + 2port
lenIPv6
=
net
.
IPv6len
+
2
// ipv6 + 2port
lenDmBase
=
2
// 1addrLen + 2port, plus addrLen
lenHmacSha1
=
10
)
// This function is copied from shadowsocks library with some modification.
// This function is copied from shadowsocks library with some modification.
func
(
s
*
ShadowServer
)
getRequest
()
(
host
string
,
ota
bool
,
err
error
)
{
func
(
h
*
shadowHandler
)
getRequest
(
conn
net
.
Conn
)
(
host
string
,
err
error
)
{
// buf size should at least have the same size with the largest possible
// buf size should at least have the same size with the largest possible
// request size (when addrType is 3, domain name has at most 256 bytes)
// request size (when addrType is 3, domain name has at most 256 bytes)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
buf
:=
make
([]
byte
,
SmallBufferSize
)
buf
:=
make
([]
byte
,
SmallBufferSize
)
// read till we get possible domain length field
// read till we get possible domain length field
s
.
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
30
*
time
.
Second
))
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
return
return
}
}
...
@@ -88,7 +141,7 @@ func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
...
@@ -88,7 +141,7 @@ func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
case
typeIPv6
:
case
typeIPv6
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
case
typeDm
:
case
typeDm
:
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
return
return
}
}
reqStart
,
reqEnd
=
idDm0
,
int
(
idDm0
+
buf
[
idDmLen
]
+
lenDmBase
)
reqStart
,
reqEnd
=
idDm0
,
int
(
idDm0
+
buf
[
idDmLen
]
+
lenDmBase
)
...
@@ -97,7 +150,7 @@ func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
...
@@ -97,7 +150,7 @@ func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
return
return
}
}
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
return
return
}
}
...
@@ -115,129 +168,9 @@ func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
...
@@ -115,129 +168,9 @@ func (s *ShadowServer) getRequest() (host string, ota bool, err error) {
// parse port
// parse port
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
host
=
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
int
(
port
)))
host
=
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
int
(
port
)))
// if specified one time auth enabled, we should verify this
if
s
.
OTA
||
addrType
&
ss
.
OneTimeAuthMask
>
0
{
ota
=
true
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
reqEnd
:
reqEnd
+
lenHmacSha1
]);
err
!=
nil
{
return
}
iv
:=
s
.
conn
.
GetIv
()
key
:=
s
.
conn
.
GetKey
()
actualHmacSha1Buf
:=
ss
.
HmacSha1
(
append
(
iv
,
key
...
),
buf
[
:
reqEnd
])
if
!
bytes
.
Equal
(
buf
[
reqEnd
:
reqEnd
+
lenHmacSha1
],
actualHmacSha1Buf
)
{
err
=
fmt
.
Errorf
(
"verify one time auth failed, iv=%v key=%v data=%v"
,
iv
,
key
,
buf
[
:
reqEnd
])
return
}
}
return
}
const
(
dataLenLen
=
2
hmacSha1Len
=
10
idxData0
=
dataLenLen
+
hmacSha1Len
)
// copyOta copies data from src to dst with ota verification.
//
// This function is copied from shadowsocks library with some modification.
func
(
s
*
ShadowServer
)
copyOta
(
dst
net
.
Conn
,
src
*
ss
.
Conn
)
(
int64
,
error
)
{
// sometimes it have to fill large block
buf
:=
make
([]
byte
,
LargeBufferSize
)
for
{
src
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
ReadTimeout
))
if
n
,
err
:=
io
.
ReadFull
(
src
,
buf
[
:
dataLenLen
+
hmacSha1Len
]);
err
!=
nil
{
return
int64
(
n
),
err
}
src
.
SetReadDeadline
(
time
.
Time
{})
dataLen
:=
binary
.
BigEndian
.
Uint16
(
buf
[
:
dataLenLen
])
expectedHmacSha1
:=
buf
[
dataLenLen
:
idxData0
]
var
dataBuf
[]
byte
if
len
(
buf
)
<
int
(
idxData0
+
dataLen
)
{
dataBuf
=
make
([]
byte
,
dataLen
)
}
else
{
dataBuf
=
buf
[
idxData0
:
idxData0
+
dataLen
]
}
if
n
,
err
:=
io
.
ReadFull
(
src
,
dataBuf
);
err
!=
nil
{
return
int64
(
n
),
err
}
chunkIdBytes
:=
make
([]
byte
,
4
)
chunkId
:=
src
.
GetAndIncrChunkId
()
binary
.
BigEndian
.
PutUint32
(
chunkIdBytes
,
chunkId
)
actualHmacSha1
:=
ss
.
HmacSha1
(
append
(
src
.
GetIv
(),
chunkIdBytes
...
),
dataBuf
)
if
!
bytes
.
Equal
(
expectedHmacSha1
,
actualHmacSha1
)
{
return
0
,
errors
.
New
(
"ota error: mismatch"
)
}
if
n
,
err
:=
dst
.
Write
(
dataBuf
);
err
!=
nil
{
return
int64
(
n
),
err
}
}
}
func
(
s
*
ShadowServer
)
transportOTA
(
sc
*
ss
.
Conn
,
cc
net
.
Conn
)
(
err
error
)
{
errc
:=
make
(
chan
error
,
2
)
go
func
()
{
_
,
err
:=
io
.
Copy
(
&
shadowConn
{
conn
:
sc
},
cc
)
errc
<-
err
}()
go
func
()
{
_
,
err
:=
s
.
copyOta
(
cc
,
sc
)
errc
<-
err
}()
select
{
case
err
=
<-
errc
:
//glog.V(LWARNING).Infoln("transport exit", err)
}
return
}
// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
// we wrap around it to make io.Copy happy
type
shadowConn
struct
{
conn
*
ss
.
Conn
}
func
(
c
*
shadowConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
c
.
conn
.
Read
(
b
)
}
func
(
c
*
shadowConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
n
=
len
(
b
)
// force byte length consistent
_
,
err
=
c
.
conn
.
Write
(
b
)
return
return
}
}
func
(
c
*
shadowConn
)
Close
()
error
{
return
c
.
conn
.
Close
()
}
func
(
c
*
shadowConn
)
LocalAddr
()
net
.
Addr
{
return
c
.
conn
.
LocalAddr
()
}
func
(
c
*
shadowConn
)
RemoteAddr
()
net
.
Addr
{
return
c
.
conn
.
RemoteAddr
()
}
func
(
c
*
shadowConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetDeadline
(
t
)
}
func
(
c
*
shadowConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetReadDeadline
(
t
)
}
func
(
c
*
shadowConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
type
ShadowUdpServer
struct
{
type
ShadowUdpServer
struct
{
Base
*
ProxyServer
Base
*
ProxyServer
TTL
int
TTL
int
...
...
ssocks/ssocks.go
deleted
100644 → 0
View file @
9884015d
package
ssocks
import
(
"encoding/binary"
"fmt"
"io"
"net"
"net/url"
"strconv"
"time"
"github.com/go-log/log"
"github.com/ginuerzh/gost"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
)
// Due to in/out byte length is inconsistent of the shadowsocks.Conn.Write,
// we wrap around it to make io.Copy happy
type
shadowConn
struct
{
conn
net
.
Conn
}
func
NewConn
(
conn
net
.
Conn
)
net
.
Conn
{
return
&
shadowConn
{
conn
:
conn
}
}
func
(
c
*
shadowConn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
return
c
.
conn
.
Read
(
b
)
}
func
(
c
*
shadowConn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
n
=
len
(
b
)
// force byte length consistent
_
,
err
=
c
.
conn
.
Write
(
b
)
return
}
func
(
c
*
shadowConn
)
Close
()
error
{
return
c
.
conn
.
Close
()
}
func
(
c
*
shadowConn
)
LocalAddr
()
net
.
Addr
{
return
c
.
conn
.
LocalAddr
()
}
func
(
c
*
shadowConn
)
RemoteAddr
()
net
.
Addr
{
return
c
.
conn
.
RemoteAddr
()
}
func
(
c
*
shadowConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetDeadline
(
t
)
}
func
(
c
*
shadowConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetReadDeadline
(
t
)
}
func
(
c
*
shadowConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
const
(
idType
=
0
// address type index
idIP0
=
1
// ip addres start index
idDmLen
=
1
// domain address length index
idDm0
=
2
// domain address start index
typeIPv4
=
1
// type is ipv4 address
typeDm
=
3
// type is domain address
typeIPv6
=
4
// type is ipv6 address
lenIPv4
=
net
.
IPv4len
+
2
// ipv4 + 2port
lenIPv6
=
net
.
IPv6len
+
2
// ipv6 + 2port
lenDmBase
=
2
// 1addrLen + 2port, plus addrLen
lenHmacSha1
=
10
)
type
ShadowServer
struct
{
conn
net
.
Conn
base
gost
.
Server
}
func
NewServer
(
conn
net
.
Conn
,
cipher
*
url
.
Userinfo
,
base
gost
.
Server
)
(
*
ShadowServer
,
error
)
{
method
:=
cipher
.
Username
()
password
,
_
:=
cipher
.
Password
()
cp
,
err
:=
ss
.
NewCipher
(
method
,
password
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
ShadowServer
{
conn
:
ss
.
NewConn
(
conn
,
cp
),
base
:
base
},
nil
}
func
(
s
*
ShadowServer
)
Serve
()
error
{
log
.
Logf
(
"[ss] %s - %s"
,
s
.
conn
.
RemoteAddr
(),
s
.
conn
.
LocalAddr
())
addr
,
err
:=
s
.
getRequest
()
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s - %s : %s"
,
s
.
conn
.
RemoteAddr
(),
s
.
conn
.
LocalAddr
(),
err
)
return
err
}
log
.
Logf
(
"[ss] %s -> %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
cc
,
err
:=
s
.
base
.
Chain
()
.
Dial
(
addr
)
if
err
!=
nil
{
log
.
Logf
(
"[ss] %s -> %s : %s"
,
s
.
conn
.
RemoteAddr
(),
addr
,
err
)
return
err
}
defer
cc
.
Close
()
log
.
Logf
(
"[ss] %s <-> %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
defer
log
.
Logf
(
"[ss] %s >-< %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
return
gost
.
Transport
(
&
shadowConn
{
conn
:
s
.
conn
},
cc
)
}
// This function is copied from shadowsocks library with some modification.
func
(
s
*
ShadowServer
)
getRequest
()
(
host
string
,
err
error
)
{
// buf size should at least have the same size with the largest possible
// request size (when addrType is 3, domain name has at most 256 bytes)
// 1(addrType) + 1(lenByte) + 256(max length address) + 2(port)
buf
:=
make
([]
byte
,
gost
.
SmallBufferSize
)
// read till we get possible domain length field
s
.
conn
.
SetReadDeadline
(
time
.
Now
()
.
Add
(
30
*
time
.
Second
))
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
:
idType
+
1
]);
err
!=
nil
{
return
}
var
reqStart
,
reqEnd
int
addrType
:=
buf
[
idType
]
switch
addrType
&
ss
.
AddrMask
{
case
typeIPv4
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv4
case
typeIPv6
:
reqStart
,
reqEnd
=
idIP0
,
idIP0
+
lenIPv6
case
typeDm
:
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
idType
+
1
:
idDmLen
+
1
]);
err
!=
nil
{
return
}
reqStart
,
reqEnd
=
idDm0
,
int
(
idDm0
+
buf
[
idDmLen
]
+
lenDmBase
)
default
:
err
=
fmt
.
Errorf
(
"addr type %d not supported"
,
addrType
&
ss
.
AddrMask
)
return
}
if
_
,
err
=
io
.
ReadFull
(
s
.
conn
,
buf
[
reqStart
:
reqEnd
]);
err
!=
nil
{
return
}
// Return string for typeIP is not most efficient, but browsers (Chrome,
// Safari, Firefox) all seems using typeDm exclusively. So this is not a
// big problem.
switch
addrType
&
ss
.
AddrMask
{
case
typeIPv4
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv4len
])
.
String
()
case
typeIPv6
:
host
=
net
.
IP
(
buf
[
idIP0
:
idIP0
+
net
.
IPv6len
])
.
String
()
case
typeDm
:
host
=
string
(
buf
[
idDm0
:
idDm0
+
buf
[
idDmLen
]])
}
// parse port
port
:=
binary
.
BigEndian
.
Uint16
(
buf
[
reqEnd
-
2
:
reqEnd
])
host
=
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
int
(
port
)))
return
}
tcp/client.go
View file @
822cc6ac
...
@@ -14,8 +14,8 @@ import (
...
@@ -14,8 +14,8 @@ import (
"github.com/ginuerzh/gosocks4"
"github.com/ginuerzh/gosocks4"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gost"
"github.com/ginuerzh/gost/socks"
"github.com/ginuerzh/gost/socks"
"github.com/ginuerzh/gost/ssocks"
"github.com/go-log/log"
"github.com/go-log/log"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
)
)
...
@@ -45,8 +45,9 @@ func (c *nodeClient) Dial(conn net.Conn, addr string) (net.Conn, error) {
...
@@ -45,8 +45,9 @@ func (c *nodeClient) Dial(conn net.Conn, addr string) (net.Conn, error) {
gosocks5
.
MethodUserPass
,
gosocks5
.
MethodUserPass
,
socks
.
MethodTLS
,
socks
.
MethodTLS
,
)
)
if
len
(
c
.
options
.
users
)
>
0
{
users
:=
c
.
options
.
BaseOptions
()
.
Users
selector
.
User
=
&
c
.
options
.
users
[
0
]
if
len
(
users
)
>
0
{
selector
.
User
=
&
users
[
0
]
}
}
cc
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
cc
:=
gosocks5
.
ClientConn
(
conn
,
selector
)
...
@@ -69,9 +70,10 @@ func (c *nodeClient) dial(conn net.Conn, addr string) (net.Conn, error) {
...
@@ -69,9 +70,10 @@ func (c *nodeClient) dial(conn net.Conn, addr string) (net.Conn, error) {
}
}
var
method
,
password
string
var
method
,
password
string
if
len
(
c
.
options
.
users
)
>
0
{
users
:=
c
.
options
.
BaseOptions
()
.
Users
method
=
c
.
options
.
users
[
0
]
.
Username
()
if
len
(
users
)
>
0
{
password
,
_
=
c
.
options
.
users
[
0
]
.
Password
()
method
=
users
[
0
]
.
Username
()
password
,
_
=
users
[
0
]
.
Password
()
}
}
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
cipher
,
err
:=
ss
.
NewCipher
(
method
,
password
)
...
@@ -83,7 +85,7 @@ func (c *nodeClient) dial(conn net.Conn, addr string) (net.Conn, error) {
...
@@ -83,7 +85,7 @@ func (c *nodeClient) dial(conn net.Conn, addr string) (net.Conn, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
conn
=
ssocks
.
Ne
wConn
(
sc
)
conn
=
gost
.
Shado
wConn
(
sc
)
case
"socks5"
:
case
"socks5"
:
host
,
port
,
err
:=
net
.
SplitHostPort
(
addr
)
host
,
port
,
err
:=
net
.
SplitHostPort
(
addr
)
...
@@ -155,8 +157,9 @@ func (c *nodeClient) dial(conn net.Conn, addr string) (net.Conn, error) {
...
@@ -155,8 +157,9 @@ func (c *nodeClient) dial(conn net.Conn, addr string) (net.Conn, error) {
Header
:
make
(
http
.
Header
),
Header
:
make
(
http
.
Header
),
}
}
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
req
.
Header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
if
len
(
c
.
options
.
users
)
>
0
{
users
:=
c
.
options
.
BaseOptions
()
.
Users
user
:=
c
.
options
.
users
[
0
]
if
len
(
users
)
>
0
{
user
:=
users
[
0
]
s
:=
user
.
String
()
s
:=
user
.
String
()
if
_
,
set
:=
user
.
Password
();
!
set
{
if
_
,
set
:=
user
.
Password
();
!
set
{
s
+=
":"
s
+=
":"
...
...
tcp/options.go
View file @
822cc6ac
package
tcp
package
tcp
import
(
import
(
"net/url"
"github.com/ginuerzh/gost"
"github.com/ginuerzh/gost"
)
)
type
nodeOptions
struct
{
type
nodeOptions
struct
{
base
*
gost
.
BaseOptions
base
*
gost
.
BaseOptions
users
[]
url
.
Userinfo
`opt:"users"`
// authentication for proxy
certFile
string
`opt:"cert"`
certFile
string
`opt:"cert"`
keyFile
string
`opt:"key"`
keyFile
string
`opt:"key"`
serverName
string
`opt:"server_name"`
serverName
string
`opt:"server_name"`
...
@@ -19,14 +16,6 @@ func (o *nodeOptions) BaseOptions() *gost.BaseOptions {
...
@@ -19,14 +16,6 @@ func (o *nodeOptions) BaseOptions() *gost.BaseOptions {
return
o
.
base
return
o
.
base
}
}
func
UsersOption
(
users
...
url
.
Userinfo
)
gost
.
Option
{
return
func
(
opts
gost
.
Options
)
{
if
o
,
ok
:=
opts
.
(
*
nodeOptions
);
ok
{
o
.
users
=
users
}
}
}
func
(
o
*
nodeOptions
)
ServerNameOption
(
n
string
)
gost
.
Option
{
func
(
o
*
nodeOptions
)
ServerNameOption
(
n
string
)
gost
.
Option
{
return
func
(
opts
gost
.
Options
)
{
return
func
(
opts
gost
.
Options
)
{
if
o
,
ok
:=
opts
.
(
*
nodeOptions
);
ok
{
if
o
,
ok
:=
opts
.
(
*
nodeOptions
);
ok
{
...
...
tcp/server.go
View file @
822cc6ac
...
@@ -4,13 +4,12 @@ import (
...
@@ -4,13 +4,12 @@ import (
"bufio"
"bufio"
"net"
"net"
"net/http"
"net/http"
"net/url"
"weed-fs/go/glog"
"github.com/ginuerzh/gosocks4"
"github.com/ginuerzh/gosocks4"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gosocks5"
"github.com/ginuerzh/gost"
"github.com/ginuerzh/gost"
"github.com/ginuerzh/gost/ssocks"
"github.com/ginuerzh/gost/ssocks"
"github.com/go-log/log"
)
)
type
nodeServer
struct
{
type
nodeServer
struct
{
...
@@ -42,26 +41,28 @@ func (s *nodeServer) Run() error {
...
@@ -42,26 +41,28 @@ func (s *nodeServer) Run() error {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
go
s
.
handleConn
(
conn
)
go
func
(
c
net
.
Conn
)
{
defer
c
.
Close
()
s
.
handleConn
(
c
)
}(
conn
)
}
}
}
}
func
(
s
*
nodeServer
)
handleConn
(
conn
net
.
Conn
)
{
func
(
s
*
nodeServer
)
handleConn
(
conn
net
.
Conn
)
{
defer
conn
.
Close
()
switch
s
.
options
.
BaseOptions
()
.
Protocol
{
switch
s
.
options
.
BaseOptions
()
.
Protocol
{
case
"ss"
:
// shadowsocks
case
"ss"
:
// shadowsocks
var
cipher
url
.
Userinfo
server
,
err
:=
ssocks
.
NewServer
(
conn
,
s
)
if
len
(
s
.
options
.
users
)
>
0
{
if
err
!=
nil
{
cipher
=
s
.
options
.
users
[
0
]
log
.
Log
(
"[ss]"
,
err
)
}
}
server
:=
ssocks
.
NewServer
(
conn
,
&
cipher
,
s
)
server
.
Serve
()
server
.
Serve
()
return
return
case
"http"
:
case
"http"
:
req
,
err
:=
http
.
ReadRequest
(
bufio
.
NewReader
(
conn
))
req
,
err
:=
http
.
ReadRequest
(
bufio
.
NewReader
(
conn
))
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[http]"
,
err
)
log
.
Log
(
"[http]"
,
err
)
return
return
}
}
NewHttpServer
(
conn
,
s
)
.
HandleRequest
(
req
)
NewHttpServer
(
conn
,
s
)
.
HandleRequest
(
req
)
...
@@ -70,7 +71,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
...
@@ -70,7 +71,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
conn
=
gosocks5
.
ServerConn
(
conn
,
s
.
selector
)
conn
=
gosocks5
.
ServerConn
(
conn
,
s
.
selector
)
req
,
err
:=
gosocks5
.
ReadRequest
(
conn
)
req
,
err
:=
gosocks5
.
ReadRequest
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks5]"
,
err
)
log
.
Log
(
"[socks5]"
,
err
)
return
return
}
}
NewSocks5Server
(
conn
,
s
)
.
HandleRequest
(
req
)
NewSocks5Server
(
conn
,
s
)
.
HandleRequest
(
req
)
...
@@ -78,7 +79,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
...
@@ -78,7 +79,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
case
"socks4"
,
"socks4a"
:
case
"socks4"
,
"socks4a"
:
req
,
err
:=
gosocks4
.
ReadRequest
(
conn
)
req
,
err
:=
gosocks4
.
ReadRequest
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks4]"
,
err
)
log
.
Log
(
"[socks4]"
,
err
)
return
return
}
}
NewSocks4Server
(
conn
,
s
)
.
HandleRequest
(
req
)
NewSocks4Server
(
conn
,
s
)
.
HandleRequest
(
req
)
...
@@ -88,7 +89,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
...
@@ -88,7 +89,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
br
:=
bufio
.
NewReader
(
conn
)
br
:=
bufio
.
NewReader
(
conn
)
b
,
err
:=
br
.
Peek
(
1
)
b
,
err
:=
br
.
Peek
(
1
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
err
)
log
.
Log
(
err
)
return
return
}
}
...
@@ -96,7 +97,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
...
@@ -96,7 +97,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
case
gosocks4
.
Ver4
:
case
gosocks4
.
Ver4
:
req
,
err
:=
gosocks4
.
ReadRequest
(
br
)
req
,
err
:=
gosocks4
.
ReadRequest
(
br
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks4]"
,
err
)
log
.
Log
(
"[socks4]"
,
err
)
return
return
}
}
NewSocks4Server
(
conn
,
s
)
.
HandleRequest
(
req
)
NewSocks4Server
(
conn
,
s
)
.
HandleRequest
(
req
)
...
@@ -104,24 +105,24 @@ func (s *nodeServer) handleConn(conn net.Conn) {
...
@@ -104,24 +105,24 @@ func (s *nodeServer) handleConn(conn net.Conn) {
case
gosocks5
.
Ver5
:
case
gosocks5
.
Ver5
:
methods
,
err
:=
gosocks5
.
ReadMethods
(
br
)
methods
,
err
:=
gosocks5
.
ReadMethods
(
br
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks5]"
,
err
)
log
.
Log
(
"[socks5]"
,
err
)
return
return
}
}
method
:=
s
.
selector
.
Select
(
methods
...
)
method
:=
s
.
selector
.
Select
(
methods
...
)
if
_
,
err
:=
conn
.
Write
([]
byte
{
gosocks5
.
Ver5
,
method
});
err
!=
nil
{
if
_
,
err
:=
conn
.
Write
([]
byte
{
gosocks5
.
Ver5
,
method
});
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks5] select:"
,
err
)
log
.
Log
(
"[socks5] select:"
,
err
)
return
return
}
}
c
,
err
:=
s
.
selector
.
OnSelected
(
method
,
conn
)
c
,
err
:=
s
.
selector
.
OnSelected
(
method
,
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks5] onselected:"
,
err
)
log
.
Log
(
"[socks5] onselected:"
,
err
)
return
return
}
}
conn
=
c
conn
=
c
req
,
err
:=
gosocks5
.
ReadRequest
(
conn
)
req
,
err
:=
gosocks5
.
ReadRequest
(
conn
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[socks5] request:"
,
err
)
log
.
Log
(
"[socks5] request:"
,
err
)
return
return
}
}
NewSocks5Server
(
conn
,
s
)
.
HandleRequest
(
req
)
NewSocks5Server
(
conn
,
s
)
.
HandleRequest
(
req
)
...
@@ -129,7 +130,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
...
@@ -129,7 +130,7 @@ func (s *nodeServer) handleConn(conn net.Conn) {
default
:
// http
default
:
// http
req
,
err
:=
http
.
ReadRequest
(
br
)
req
,
err
:=
http
.
ReadRequest
(
br
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
"[http]"
,
err
)
log
.
Log
(
"[http]"
,
err
)
return
return
}
}
NewHttpServer
(
conn
,
s
)
.
HandleRequest
(
req
)
NewHttpServer
(
conn
,
s
)
.
HandleRequest
(
req
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment