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
9ccddf3c
Commit
9ccddf3c
authored
Mar 23, 2015
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add shadowsocks compatible
parent
bdda0cde
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
188 additions
and
36 deletions
+188
-36
gost.go
gost.go
+149
-29
log.go
log.go
+37
-7
main.go
main.go
+2
-0
No files found.
gost.go
View file @
9ccddf3c
...
@@ -13,7 +13,10 @@ import (
...
@@ -13,7 +13,10 @@ import (
"strconv"
"strconv"
"strings"
"strings"
//"sync/atomic"
//"sync/atomic"
//"fmt"
"encoding/binary"
"fmt"
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
"net/url"
"time"
"time"
)
)
...
@@ -24,6 +27,7 @@ const (
...
@@ -24,6 +27,7 @@ const (
type
Gost
struct
{
type
Gost
struct
{
Laddr
,
Saddr
,
Proxy
string
Laddr
,
Saddr
,
Proxy
string
Shadows
bool
// shadowsocks compatible
}
}
func
(
g
*
Gost
)
Run
()
error
{
func
(
g
*
Gost
)
Run
()
error
{
...
@@ -43,6 +47,7 @@ func (g *Gost) Run() error {
...
@@ -43,6 +47,7 @@ func (g *Gost) Run() error {
log
.
Println
(
"accept:"
,
err
)
log
.
Println
(
"accept:"
,
err
)
continue
continue
}
}
//log.Println("accept", conn.RemoteAddr().String())
go
g
.
handle
(
conn
)
go
g
.
handle
(
conn
)
}
}
...
@@ -62,7 +67,13 @@ func (g *Gost) handle(conn net.Conn) {
...
@@ -62,7 +67,13 @@ func (g *Gost) handle(conn net.Conn) {
}
}
func
(
g
*
Gost
)
cli
(
conn
net
.
Conn
)
{
func
(
g
*
Gost
)
cli
(
conn
net
.
Conn
)
{
lg
:=
NewLog
()
lg
:=
NewLog
(
true
)
defer
func
()
{
lg
.
Logln
()
lg
.
Flush
()
}()
lg
.
Logln
(
"accept"
,
conn
.
(
*
net
.
TCPConn
)
.
RemoteAddr
()
.
String
())
sconn
,
err
:=
g
.
connect
(
g
.
Saddr
)
sconn
,
err
:=
g
.
connect
(
g
.
Saddr
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -80,6 +91,48 @@ func (g *Gost) cli(conn net.Conn) {
...
@@ -80,6 +91,48 @@ func (g *Gost) cli(conn net.Conn) {
}
}
lg
.
Logln
(
">>>|"
,
[]
byte
{
5
,
1
,
0
})
lg
.
Logln
(
">>>|"
,
[]
byte
{
5
,
1
,
0
})
if
g
.
Shadows
{
lg
.
Logln
(
"shadowsocks, aes-256-cfb"
)
cipher
,
_
:=
shadowsocks
.
NewCipher
(
"aes-256-cfb"
,
"123456"
)
conn
=
shadowsocks
.
NewConn
(
conn
,
cipher
)
addr
,
port
,
extra
,
err
:=
getRequest
(
conn
)
if
err
!=
nil
{
lg
.
Logln
(
err
)
return
}
lg
.
Logln
(
addr
,
port
)
cmd
:=
NewCmd
(
CmdConnect
,
AddrDomain
,
addr
,
port
)
if
err
=
cmd
.
Write
(
sconn
);
err
!=
nil
{
lg
.
Logln
(
err
)
return
}
lg
.
Logln
(
">>>|"
,
cmd
)
if
cmd
,
err
=
ReadCmd
(
sconn
);
err
!=
nil
{
lg
.
Logln
(
err
)
return
}
lg
.
Logln
(
"<<<|"
,
cmd
)
if
cmd
.
Cmd
!=
Succeeded
{
conn
.
Write
([]
byte
(
"HTTP/1.1 503 Service unavailable
\r\n
"
+
"Proxy-Agent: gost/1.0
\r\n\r\n
"
))
return
}
if
extra
!=
nil
{
if
_
,
err
:=
sconn
.
Write
(
extra
);
err
!=
nil
{
log
.
Println
(
err
)
return
}
}
g
.
transport
(
conn
,
sconn
)
return
}
b
:=
make
([]
byte
,
8192
)
b
:=
make
([]
byte
,
8192
)
n
,
err
:=
io
.
ReadFull
(
sconn
,
b
[
:
2
])
n
,
err
:=
io
.
ReadFull
(
sconn
,
b
[
:
2
])
...
@@ -94,7 +147,7 @@ func (g *Gost) cli(conn net.Conn) {
...
@@ -94,7 +147,7 @@ func (g *Gost) cli(conn net.Conn) {
lg
.
Logln
(
err
)
lg
.
Logln
(
err
)
return
return
}
}
//log.Println(b[:n])
if
b
[
0
]
==
5
{
// socks5,NO AUTHENTICATION
if
b
[
0
]
==
5
{
// socks5,NO AUTHENTICATION
lg
.
Logln
(
"|>>>"
,
b
[
:
n
])
lg
.
Logln
(
"|>>>"
,
b
[
:
n
])
...
@@ -130,9 +183,6 @@ func (g *Gost) cli(conn net.Conn) {
...
@@ -130,9 +183,6 @@ func (g *Gost) cli(conn net.Conn) {
}
}
lg
.
Logln
(
"|<<<"
,
cmd
)
lg
.
Logln
(
"|<<<"
,
cmd
)
lg
.
Logln
()
lg
.
Flush
()
g
.
transport
(
conn
,
sconn
)
g
.
transport
(
conn
,
sconn
)
return
return
}
}
...
@@ -192,14 +242,17 @@ func (g *Gost) cli(conn net.Conn) {
...
@@ -192,14 +242,17 @@ func (g *Gost) cli(conn net.Conn) {
}
}
}
}
lg
.
Logln
()
lg
.
Flush
()
g
.
transport
(
conn
,
sconn
)
g
.
transport
(
conn
,
sconn
)
}
}
func
(
g
*
Gost
)
srv
(
conn
net
.
Conn
)
{
func
(
g
*
Gost
)
srv
(
conn
net
.
Conn
)
{
b
:=
make
([]
byte
,
8192
)
b
:=
make
([]
byte
,
8192
)
lg
:=
NewLog
()
lg
:=
NewLog
(
true
)
defer
func
()
{
lg
.
Logln
()
lg
.
Flush
()
}()
lg
.
Logln
(
"accept"
,
conn
.
(
*
net
.
TCPConn
)
.
RemoteAddr
()
.
String
())
n
,
err
:=
conn
.
Read
(
b
)
n
,
err
:=
conn
.
Read
(
b
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -306,36 +359,34 @@ func (g *Gost) connect(addr string) (net.Conn, error) {
...
@@ -306,36 +359,34 @@ func (g *Gost) connect(addr string) (net.Conn, error) {
}
}
pconn
,
err
:=
net
.
DialTCP
(
"tcp"
,
nil
,
paddr
)
pconn
,
err
:=
net
.
DialTCP
(
"tcp"
,
nil
,
paddr
)
if
err
!=
nil
{
if
err
!=
nil
{
log
.
Println
(
err
)
return
nil
,
err
return
nil
,
err
}
}
b
:=
make
([]
byte
,
1500
)
header
:=
http
.
Header
{}
buffer
:=
bytes
.
NewBuffer
(
b
)
header
.
Set
(
"Proxy-Connection"
,
"keep-alive"
)
buffer
.
WriteString
(
"CONNECT "
+
addr
+
" HTTP/1.1
\r\n
"
)
req
:=
&
http
.
Request
{
buffer
.
WriteString
(
"Host: "
+
addr
+
"
\r\n
"
)
Method
:
"CONNECT"
,
buffer
.
WriteString
(
"Proxy-Connection: keep-alive
\r\n\r\n
"
)
URL
:
&
url
.
URL
{
Host
:
addr
},
if
_
,
err
=
pconn
.
Write
(
buffer
.
Bytes
());
err
!=
nil
{
Host
:
addr
,
Header
:
header
,
}
if
err
:=
req
.
Write
(
pconn
);
err
!=
nil
{
log
.
Println
(
err
)
pconn
.
Close
()
pconn
.
Close
()
return
nil
,
err
return
nil
,
err
}
}
r
:=
""
resp
,
err
:=
http
.
ReadResponse
(
bufio
.
NewReader
(
pconn
),
req
)
for
!
strings
.
HasSuffix
(
r
,
"
\r\n\r\n
"
)
{
if
err
!=
nil
{
n
:=
0
log
.
Println
(
err
)
if
n
,
err
=
pconn
.
Read
(
b
);
err
!=
nil
{
pconn
.
Close
()
return
nil
,
err
}
r
+=
string
(
b
[
:
n
])
}
log
.
Println
(
r
)
if
!
strings
.
Contains
(
r
,
"200"
)
{
log
.
Println
(
"connection failed:
\n
"
,
r
)
err
=
errors
.
New
(
r
)
pconn
.
Close
()
pconn
.
Close
()
return
nil
,
err
return
nil
,
err
}
}
if
resp
.
StatusCode
!=
http
.
StatusOK
{
pconn
.
Close
()
return
nil
,
errors
.
New
(
resp
.
Status
)
}
return
pconn
,
nil
return
pconn
,
nil
}
}
...
@@ -361,3 +412,72 @@ func (g *Gost) transport(conn, conn2 net.Conn) (err error) {
...
@@ -361,3 +412,72 @@ func (g *Gost) transport(conn, conn2 net.Conn) (err error) {
return
return
}
}
func
getRequest
(
conn
net
.
Conn
)
(
host
string
,
port
uint16
,
extra
[]
byte
,
err
error
)
{
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
=
1
+
net
.
IPv4len
+
2
// 1addrType + ipv4 + 2port
lenIPv6
=
1
+
net
.
IPv6len
+
2
// 1addrType + ipv6 + 2port
lenDmBase
=
1
+
1
+
2
// 1addrType + 1addrLen + 2port, plus addrLen
)
// 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
,
260
)
var
n
int
// read till we get possible domain length field
//ss.SetReadTimeout(conn)
if
n
,
err
=
io
.
ReadAtLeast
(
conn
,
buf
,
idDmLen
+
1
);
err
!=
nil
{
log
.
Println
(
err
)
return
}
log
.
Println
(
buf
[
:
n
])
reqLen
:=
-
1
switch
buf
[
idType
]
{
case
typeIPv4
:
reqLen
=
lenIPv4
case
typeIPv6
:
reqLen
=
lenIPv6
case
typeDm
:
reqLen
=
int
(
buf
[
idDmLen
])
+
lenDmBase
default
:
err
=
fmt
.
Errorf
(
"addr type %d not supported"
,
buf
[
idType
])
return
}
if
n
<
reqLen
{
// rare case
//ss.SetReadTimeout(conn)
if
_
,
err
=
io
.
ReadFull
(
conn
,
buf
[
n
:
reqLen
]);
err
!=
nil
{
log
.
Println
(
err
)
return
}
}
else
if
n
>
reqLen
{
// it's possible to read more than just the request head
extra
=
buf
[
reqLen
:
n
]
}
// 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
buf
[
idType
]
{
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
[
reqLen
-
2
:
reqLen
])
return
}
log.go
View file @
9ccddf3c
...
@@ -7,16 +7,24 @@ import (
...
@@ -7,16 +7,24 @@ import (
"os"
"os"
)
)
var
(
Debug
bool
)
type
BufferedLog
struct
{
type
BufferedLog
struct
{
buffer
*
bytes
.
Buffer
buffer
*
bytes
.
Buffer
w
io
.
WriteCloser
w
io
.
WriteCloser
}
}
func
NewLog
()
*
BufferedLog
{
func
NewLog
(
buffered
bool
)
*
BufferedLog
{
return
&
BufferedLog
{
log
:=
&
BufferedLog
{
buffer
:
&
bytes
.
Buffer
{},
w
:
os
.
Stdout
,
w
:
os
.
Stdout
,
}
}
if
buffered
{
log
.
buffer
=
&
bytes
.
Buffer
{}
}
return
log
}
}
func
NewFileLog
(
file
*
os
.
File
)
*
BufferedLog
{
func
NewFileLog
(
file
*
os
.
File
)
*
BufferedLog
{
...
@@ -27,15 +35,33 @@ func NewFileLog(file *os.File) *BufferedLog {
...
@@ -27,15 +35,33 @@ func NewFileLog(file *os.File) *BufferedLog {
}
}
func
(
log
*
BufferedLog
)
Log
(
a
...
interface
{})
(
int
,
error
)
{
func
(
log
*
BufferedLog
)
Log
(
a
...
interface
{})
(
int
,
error
)
{
return
fmt
.
Fprint
(
log
.
buffer
,
a
...
)
if
!
Debug
{
return
0
,
nil
}
if
log
.
buffer
!=
nil
{
return
fmt
.
Fprint
(
log
.
buffer
,
a
...
)
}
return
fmt
.
Fprint
(
log
.
w
,
a
...
)
}
}
func
(
log
*
BufferedLog
)
Logln
(
a
...
interface
{})
(
int
,
error
)
{
func
(
log
*
BufferedLog
)
Logln
(
a
...
interface
{})
(
int
,
error
)
{
return
fmt
.
Fprintln
(
log
.
buffer
,
a
...
)
if
!
Debug
{
return
0
,
nil
}
if
log
.
buffer
!=
nil
{
return
fmt
.
Fprintln
(
log
.
buffer
,
a
...
)
}
return
fmt
.
Fprintln
(
log
.
w
,
a
...
)
}
}
func
(
log
*
BufferedLog
)
Logf
(
format
string
,
a
...
interface
{})
(
int
,
error
)
{
func
(
log
*
BufferedLog
)
Logf
(
format
string
,
a
...
interface
{})
(
int
,
error
)
{
return
fmt
.
Fprintf
(
log
.
buffer
,
format
,
a
...
)
if
!
Debug
{
return
0
,
nil
}
if
log
.
buffer
!=
nil
{
return
fmt
.
Fprintf
(
log
.
buffer
,
format
,
a
...
)
}
return
fmt
.
Fprintf
(
log
.
w
,
format
,
a
...
)
}
}
func
(
log
*
BufferedLog
)
Flush
()
error
{
func
(
log
*
BufferedLog
)
Flush
()
error
{
...
@@ -45,6 +71,10 @@ func (log *BufferedLog) Flush() error {
...
@@ -45,6 +71,10 @@ func (log *BufferedLog) Flush() error {
}
}
}()
}()
if
!
Debug
||
log
.
buffer
==
nil
{
return
nil
}
_
,
err
:=
log
.
buffer
.
WriteTo
(
log
.
w
)
_
,
err
:=
log
.
buffer
.
WriteTo
(
log
.
w
)
return
err
return
err
}
}
main.go
View file @
9ccddf3c
...
@@ -12,6 +12,8 @@ func init() {
...
@@ -12,6 +12,8 @@ func init() {
flag
.
StringVar
(
&
gost
.
Proxy
,
"P"
,
""
,
"proxy for forward"
)
flag
.
StringVar
(
&
gost
.
Proxy
,
"P"
,
""
,
"proxy for forward"
)
flag
.
StringVar
(
&
gost
.
Saddr
,
"S"
,
""
,
"the server that connecting to"
)
flag
.
StringVar
(
&
gost
.
Saddr
,
"S"
,
""
,
"the server that connecting to"
)
flag
.
StringVar
(
&
gost
.
Laddr
,
"L"
,
":8080"
,
"listen address"
)
flag
.
StringVar
(
&
gost
.
Laddr
,
"L"
,
":8080"
,
"listen address"
)
flag
.
BoolVar
(
&
gost
.
Shadows
,
"ss"
,
false
,
"shadowsocks compatible"
)
flag
.
BoolVar
(
&
Debug
,
"d"
,
false
,
"debug option"
)
flag
.
Parse
()
flag
.
Parse
()
log
.
SetFlags
(
log
.
LstdFlags
|
log
.
Lshortfile
)
log
.
SetFlags
(
log
.
LstdFlags
|
log
.
Lshortfile
)
...
...
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