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
8861ffba
Commit
8861ffba
authored
Jan 24, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#73: Add shadowsocks UDP relay support
parent
321b0371
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
4107 additions
and
153 deletions
+4107
-153
cmd/gost/vendor/github.com/Yawning/chacha20/LICENSE
cmd/gost/vendor/github.com/Yawning/chacha20/LICENSE
+122
-0
cmd/gost/vendor/github.com/Yawning/chacha20/README.md
cmd/gost/vendor/github.com/Yawning/chacha20/README.md
+14
-0
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20.go
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20.go
+273
-0
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.go
...gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.go
+95
-0
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.py
...gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.py
+1303
-0
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.s
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.s
+1187
-0
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_ref.go
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_ref.go
+392
-0
cmd/gost/vendor/github.com/ginuerzh/gost/forward.go
cmd/gost/vendor/github.com/ginuerzh/gost/forward.go
+22
-19
cmd/gost/vendor/github.com/ginuerzh/gost/gost.go
cmd/gost/vendor/github.com/ginuerzh/gost/gost.go
+1
-1
cmd/gost/vendor/github.com/ginuerzh/gost/node.go
cmd/gost/vendor/github.com/ginuerzh/gost/node.go
+1
-1
cmd/gost/vendor/github.com/ginuerzh/gost/server.go
cmd/gost/vendor/github.com/ginuerzh/gost/server.go
+7
-3
cmd/gost/vendor/github.com/ginuerzh/gost/ss.go
cmd/gost/vendor/github.com/ginuerzh/gost/ss.go
+107
-41
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go
...hub.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go
+28
-12
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go
.../github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go
+135
-0
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go
...ub.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go
+265
-0
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go
...github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go
+5
-5
cmd/gost/vendor/vendor.json
cmd/gost/vendor/vendor.json
+12
-6
forward.go
forward.go
+22
-19
gost.go
gost.go
+1
-1
node.go
node.go
+1
-1
server.go
server.go
+7
-3
ss.go
ss.go
+107
-41
No files found.
cmd/gost/vendor/github.com/Yawning/chacha20/LICENSE
0 → 100644
View file @
8861ffba
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
cmd/gost/vendor/github.com/Yawning/chacha20/README.md
0 → 100644
View file @
8861ffba
### chacha20 - ChaCha20
#### Yawning Angel (yawning at schwanenlied dot me)
Yet another Go ChaCha20 implementation. Everything else I found was slow,
didn't support all the variants I need to use, or relied on cgo to go fast.
Features:
*
20 round, 256 bit key only. Everything else is pointless and stupid.
*
IETF 96 bit nonce variant.
*
XChaCha 24 byte nonce variant.
*
SSE2 and AVX2 support on amd64 targets.
*
Incremental encrypt/decrypt support, unlike golang.org/x/crypto/salsa20.
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20.go
0 → 100644
View file @
8861ffba
// chacha20.go - A ChaCha stream cipher implementation.
//
// To the extent possible under law, Yawning Angel has waived all copyright
// and related or neighboring rights to chacha20, using the Creative
// Commons "CC0" public domain dedication. See LICENSE or
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
package
chacha20
import
(
"crypto/cipher"
"encoding/binary"
"errors"
"math"
"runtime"
)
const
(
// KeySize is the ChaCha20 key size in bytes.
KeySize
=
32
// NonceSize is the ChaCha20 nonce size in bytes.
NonceSize
=
8
// INonceSize is the IETF ChaCha20 nonce size in bytes.
INonceSize
=
12
// XNonceSize is the XChaCha20 nonce size in bytes.
XNonceSize
=
24
// HNonceSize is the HChaCha20 nonce size in bytes.
HNonceSize
=
16
// BlockSize is the ChaCha20 block size in bytes.
BlockSize
=
64
stateSize
=
16
chachaRounds
=
20
// The constant "expand 32-byte k" as little endian uint32s.
sigma0
=
uint32
(
0x61707865
)
sigma1
=
uint32
(
0x3320646e
)
sigma2
=
uint32
(
0x79622d32
)
sigma3
=
uint32
(
0x6b206574
)
)
var
(
// ErrInvalidKey is the error returned when the key is invalid.
ErrInvalidKey
=
errors
.
New
(
"key length must be KeySize bytes"
)
// ErrInvalidNonce is the error returned when the nonce is invalid.
ErrInvalidNonce
=
errors
.
New
(
"nonce length must be NonceSize/INonceSize/XNonceSize bytes"
)
// ErrInvalidCounter is the error returned when the counter is invalid.
ErrInvalidCounter
=
errors
.
New
(
"block counter is invalid (out of range)"
)
useUnsafe
=
false
usingVectors
=
false
blocksFn
=
blocksRef
)
// A Cipher is an instance of ChaCha20/XChaCha20 using a particular key and
// nonce.
type
Cipher
struct
{
state
[
stateSize
]
uint32
buf
[
BlockSize
]
byte
off
int
ietf
bool
}
// Reset zeros the key data so that it will no longer appear in the process's
// memory.
func
(
c
*
Cipher
)
Reset
()
{
for
i
:=
range
c
.
state
{
c
.
state
[
i
]
=
0
}
for
i
:=
range
c
.
buf
{
c
.
buf
[
i
]
=
0
}
}
// XORKeyStream sets dst to the result of XORing src with the key stream. Dst
// and src may be the same slice but otherwise should not overlap.
func
(
c
*
Cipher
)
XORKeyStream
(
dst
,
src
[]
byte
)
{
if
len
(
dst
)
<
len
(
src
)
{
src
=
src
[
:
len
(
dst
)]
}
for
remaining
:=
len
(
src
);
remaining
>
0
;
{
// Process multiple blocks at once.
if
c
.
off
==
BlockSize
{
nrBlocks
:=
remaining
/
BlockSize
directBytes
:=
nrBlocks
*
BlockSize
if
nrBlocks
>
0
{
blocksFn
(
&
c
.
state
,
src
,
dst
,
nrBlocks
,
c
.
ietf
)
remaining
-=
directBytes
if
remaining
==
0
{
return
}
dst
=
dst
[
directBytes
:
]
src
=
src
[
directBytes
:
]
}
// If there's a partial block, generate 1 block of keystream into
// the internal buffer.
blocksFn
(
&
c
.
state
,
nil
,
c
.
buf
[
:
],
1
,
c
.
ietf
)
c
.
off
=
0
}
// Process partial blocks from the buffered keystream.
toXor
:=
BlockSize
-
c
.
off
if
remaining
<
toXor
{
toXor
=
remaining
}
if
toXor
>
0
{
for
i
,
v
:=
range
src
[
:
toXor
]
{
dst
[
i
]
=
v
^
c
.
buf
[
c
.
off
+
i
]
}
dst
=
dst
[
toXor
:
]
src
=
src
[
toXor
:
]
remaining
-=
toXor
c
.
off
+=
toXor
}
}
}
// KeyStream sets dst to the raw keystream.
func
(
c
*
Cipher
)
KeyStream
(
dst
[]
byte
)
{
for
remaining
:=
len
(
dst
);
remaining
>
0
;
{
// Process multiple blocks at once.
if
c
.
off
==
BlockSize
{
nrBlocks
:=
remaining
/
BlockSize
directBytes
:=
nrBlocks
*
BlockSize
if
nrBlocks
>
0
{
blocksFn
(
&
c
.
state
,
nil
,
dst
,
nrBlocks
,
c
.
ietf
)
remaining
-=
directBytes
if
remaining
==
0
{
return
}
dst
=
dst
[
directBytes
:
]
}
// If there's a partial block, generate 1 block of keystream into
// the internal buffer.
blocksFn
(
&
c
.
state
,
nil
,
c
.
buf
[
:
],
1
,
c
.
ietf
)
c
.
off
=
0
}
// Process partial blocks from the buffered keystream.
toCopy
:=
BlockSize
-
c
.
off
if
remaining
<
toCopy
{
toCopy
=
remaining
}
if
toCopy
>
0
{
copy
(
dst
[
:
toCopy
],
c
.
buf
[
c
.
off
:
c
.
off
+
toCopy
])
dst
=
dst
[
toCopy
:
]
remaining
-=
toCopy
c
.
off
+=
toCopy
}
}
}
// ReKey reinitializes the ChaCha20/XChaCha20 instance with the provided key
// and nonce.
func
(
c
*
Cipher
)
ReKey
(
key
,
nonce
[]
byte
)
error
{
if
len
(
key
)
!=
KeySize
{
return
ErrInvalidKey
}
switch
len
(
nonce
)
{
case
NonceSize
:
case
INonceSize
:
case
XNonceSize
:
var
subkey
[
KeySize
]
byte
var
subnonce
[
HNonceSize
]
byte
copy
(
subnonce
[
:
],
nonce
[
0
:
16
])
HChaCha
(
key
,
&
subnonce
,
&
subkey
)
key
=
subkey
[
:
]
nonce
=
nonce
[
16
:
24
]
defer
func
()
{
for
i
:=
range
subkey
{
subkey
[
i
]
=
0
}
}()
default
:
return
ErrInvalidNonce
}
c
.
Reset
()
c
.
state
[
0
]
=
sigma0
c
.
state
[
1
]
=
sigma1
c
.
state
[
2
]
=
sigma2
c
.
state
[
3
]
=
sigma3
c
.
state
[
4
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
0
:
4
])
c
.
state
[
5
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
4
:
8
])
c
.
state
[
6
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
8
:
12
])
c
.
state
[
7
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
12
:
16
])
c
.
state
[
8
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
16
:
20
])
c
.
state
[
9
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
20
:
24
])
c
.
state
[
10
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
24
:
28
])
c
.
state
[
11
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
28
:
32
])
c
.
state
[
12
]
=
0
if
len
(
nonce
)
==
INonceSize
{
c
.
state
[
13
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
0
:
4
])
c
.
state
[
14
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
4
:
8
])
c
.
state
[
15
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
8
:
12
])
c
.
ietf
=
true
}
else
{
c
.
state
[
13
]
=
0
c
.
state
[
14
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
0
:
4
])
c
.
state
[
15
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
4
:
8
])
c
.
ietf
=
false
}
c
.
off
=
BlockSize
return
nil
}
// Seek sets the block counter to a given offset.
func
(
c
*
Cipher
)
Seek
(
blockCounter
uint64
)
error
{
if
c
.
ietf
{
if
blockCounter
>
math
.
MaxUint32
{
return
ErrInvalidCounter
}
c
.
state
[
12
]
=
uint32
(
blockCounter
)
}
else
{
c
.
state
[
12
]
=
uint32
(
blockCounter
)
c
.
state
[
13
]
=
uint32
(
blockCounter
>>
32
)
}
c
.
off
=
BlockSize
return
nil
}
// NewCipher returns a new ChaCha20/XChaCha20 instance.
func
NewCipher
(
key
,
nonce
[]
byte
)
(
*
Cipher
,
error
)
{
c
:=
new
(
Cipher
)
if
err
:=
c
.
ReKey
(
key
,
nonce
);
err
!=
nil
{
return
nil
,
err
}
return
c
,
nil
}
// HChaCha is the HChaCha20 hash function used to make XChaCha.
func
HChaCha
(
key
[]
byte
,
nonce
*
[
HNonceSize
]
byte
,
out
*
[
32
]
byte
)
{
var
x
[
stateSize
]
uint32
// Last 4 slots unused, sigma hardcoded.
x
[
0
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
0
:
4
])
x
[
1
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
4
:
8
])
x
[
2
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
8
:
12
])
x
[
3
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
12
:
16
])
x
[
4
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
16
:
20
])
x
[
5
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
20
:
24
])
x
[
6
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
24
:
28
])
x
[
7
]
=
binary
.
LittleEndian
.
Uint32
(
key
[
28
:
32
])
x
[
8
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
0
:
4
])
x
[
9
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
4
:
8
])
x
[
10
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
8
:
12
])
x
[
11
]
=
binary
.
LittleEndian
.
Uint32
(
nonce
[
12
:
16
])
hChaChaRef
(
&
x
,
out
)
}
func
init
()
{
switch
runtime
.
GOARCH
{
case
"386"
,
"amd64"
:
// Abuse unsafe to skip calling binary.LittleEndian.PutUint32
// in the critical path. This is a big boost on systems that are
// little endian and not overly picky about alignment.
useUnsafe
=
true
}
}
var
_
cipher
.
Stream
=
(
*
Cipher
)(
nil
)
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.go
0 → 100644
View file @
8861ffba
// chacha20_amd64.go - AMD64 optimized chacha20.
//
// To the extent possible under law, Yawning Angel has waived all copyright
// and related or neighboring rights to chacha20, using the Creative
// Commons "CC0" public domain dedication. See LICENSE or
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
// +build amd64,!gccgo,!appengine
package
chacha20
import
(
"math"
)
var
usingAVX2
=
false
func
blocksAmd64SSE2
(
x
*
uint32
,
inp
,
outp
*
byte
,
nrBlocks
uint
)
func
blocksAmd64AVX2
(
x
*
uint32
,
inp
,
outp
*
byte
,
nrBlocks
uint
)
func
cpuidAmd64
(
cpuidParams
*
uint32
)
func
xgetbv0Amd64
(
xcrVec
*
uint32
)
func
blocksAmd64
(
x
*
[
stateSize
]
uint32
,
in
[]
byte
,
out
[]
byte
,
nrBlocks
int
,
isIetf
bool
)
{
// Probably unneeded, but stating this explicitly simplifies the assembly.
if
nrBlocks
==
0
{
return
}
if
isIetf
{
var
totalBlocks
uint64
totalBlocks
=
uint64
(
x
[
8
])
+
uint64
(
nrBlocks
)
if
totalBlocks
>
math
.
MaxUint32
{
panic
(
"chacha20: Exceeded keystream per nonce limit"
)
}
}
if
in
==
nil
{
for
i
:=
range
out
{
out
[
i
]
=
0
}
in
=
out
}
// Pointless to call the AVX2 code for just a single block, since half of
// the output gets discarded...
if
usingAVX2
&&
nrBlocks
>
1
{
blocksAmd64AVX2
(
&
x
[
0
],
&
in
[
0
],
&
out
[
0
],
uint
(
nrBlocks
))
}
else
{
blocksAmd64SSE2
(
&
x
[
0
],
&
in
[
0
],
&
out
[
0
],
uint
(
nrBlocks
))
}
}
func
supportsAVX2
()
bool
{
// https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family
const
(
osXsaveBit
=
1
<<
27
avx2Bit
=
1
<<
5
)
// Check to see if CPUID actually supports the leaf that indicates AVX2.
// CPUID.(EAX=0H, ECX=0H) >= 7
regs
:=
[
4
]
uint32
{
0x00
}
cpuidAmd64
(
&
regs
[
0
])
if
regs
[
0
]
<
7
{
return
false
}
// Check to see if the OS knows how to save/restore XMM/YMM state.
// CPUID.(EAX=01H, ECX=0H):ECX.OSXSAVE[bit 27]==1
regs
=
[
4
]
uint32
{
0x01
}
cpuidAmd64
(
&
regs
[
0
])
if
regs
[
2
]
&
osXsaveBit
==
0
{
return
false
}
xcrRegs
:=
[
2
]
uint32
{}
xgetbv0Amd64
(
&
xcrRegs
[
0
])
if
xcrRegs
[
0
]
&
6
!=
6
{
return
false
}
// Check for AVX2 support.
// CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1
regs
=
[
4
]
uint32
{
0x07
}
cpuidAmd64
(
&
regs
[
0
])
return
regs
[
1
]
&
avx2Bit
!=
0
}
func
init
()
{
blocksFn
=
blocksAmd64
usingVectors
=
true
usingAVX2
=
supportsAVX2
()
}
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.py
0 → 100644
View file @
8861ffba
This diff is collapsed.
Click to expand it.
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_amd64.s
0 → 100644
View file @
8861ffba
This diff is collapsed.
Click to expand it.
cmd/gost/vendor/github.com/Yawning/chacha20/chacha20_ref.go
0 → 100644
View file @
8861ffba
This diff is collapsed.
Click to expand it.
cmd/gost/vendor/github.com/ginuerzh/gost/forward.go
View file @
8861ffba
...
...
@@ -63,15 +63,15 @@ func (s *TcpForwardServer) handleTcpForward(conn net.Conn, raddr net.Addr) {
}
type
packet
struct
{
srcAddr
*
net
.
UDPAddr
// src address
dstAddr
*
net
.
UDPAddr
// dest address
srcAddr
string
// src address
dstAddr
string
// dest address
data
[]
byte
}
type
cnode
struct
{
chain
*
ProxyChain
conn
net
.
Conn
srcAddr
,
dstAddr
*
net
.
UDPAddr
srcAddr
,
dstAddr
string
rChan
,
wChan
chan
*
packet
err
error
ttl
time
.
Duration
...
...
@@ -146,13 +146,9 @@ func (node *cnode) run() {
timer
.
Reset
(
node
.
ttl
)
glog
.
V
(
LDEBUG
)
.
Infof
(
"[udp] %s <<< %s : length %d"
,
node
.
srcAddr
,
addr
,
n
)
if
node
.
dstAddr
.
String
()
!=
addr
.
String
()
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : dst-addr mismatch (%s)"
,
node
.
srcAddr
,
node
.
dstAddr
,
addr
)
break
}
select
{
// swap srcAddr with dstAddr
case
node
.
rChan
<-
&
packet
{
srcAddr
:
node
.
dstAddr
,
dstAddr
:
node
.
srcAddr
,
data
:
b
[
:
n
]}
:
case
node
.
rChan
<-
&
packet
{
srcAddr
:
addr
.
String
()
,
dstAddr
:
node
.
srcAddr
,
data
:
b
[
:
n
]}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : %s"
,
node
.
srcAddr
,
node
.
dstAddr
,
"recv queue is full, discard"
)
}
...
...
@@ -169,13 +165,9 @@ func (node *cnode) run() {
timer
.
Reset
(
node
.
ttl
)
glog
.
V
(
LDEBUG
)
.
Infof
(
"[udp-tun] %s <<< %s : length %d"
,
node
.
srcAddr
,
dgram
.
Header
.
Addr
.
String
(),
len
(
dgram
.
Data
))
if
dgram
.
Header
.
Addr
.
String
()
!=
node
.
dstAddr
.
String
()
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp-tun] %s <- %s : dst-addr mismatch (%s)"
,
node
.
srcAddr
,
node
.
dstAddr
,
dgram
.
Header
.
Addr
)
break
}
select
{
// swap srcAddr with dstAddr
case
node
.
rChan
<-
&
packet
{
srcAddr
:
node
.
dstAddr
,
dstAddr
:
node
.
srcAddr
,
data
:
dgram
.
Data
}
:
case
node
.
rChan
<-
&
packet
{
srcAddr
:
dgram
.
Header
.
Addr
.
String
()
,
dstAddr
:
node
.
srcAddr
,
data
:
dgram
.
Data
}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp-tun] %s <- %s : %s"
,
node
.
srcAddr
,
node
.
dstAddr
,
"recv queue is full, discard"
)
}
...
...
@@ -187,9 +179,15 @@ func (node *cnode) run() {
for
pkt
:=
range
node
.
wChan
{
timer
.
Reset
(
node
.
ttl
)
dstAddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
pkt
.
dstAddr
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
err
)
continue
}
switch
c
:=
node
.
conn
.
(
type
)
{
case
*
net
.
UDPConn
:
if
_
,
err
:=
c
.
WriteToUDP
(
pkt
.
data
,
pkt
.
dstAddr
);
err
!=
nil
{
if
_
,
err
:=
c
.
WriteToUDP
(
pkt
.
data
,
dstAddr
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
err
)
node
.
err
=
err
errChan
<-
err
...
...
@@ -198,7 +196,7 @@ func (node *cnode) run() {
glog
.
V
(
LDEBUG
)
.
Infof
(
"[udp] %s >>> %s : length %d"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
len
(
pkt
.
data
))
default
:
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
uint16
(
len
(
pkt
.
data
)),
0
,
ToSocksAddr
(
pkt
.
dstAddr
)),
pkt
.
data
)
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
uint16
(
len
(
pkt
.
data
)),
0
,
ToSocksAddr
(
dstAddr
)),
pkt
.
data
)
if
err
:=
dgram
.
Write
(
c
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp-tun] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
err
)
node
.
err
=
err
...
...
@@ -255,7 +253,7 @@ func (s *UdpForwardServer) ListenAndServe() error {
}
select
{
case
ch
<-
&
packet
{
srcAddr
:
addr
,
dstAddr
:
raddr
,
data
:
b
[
:
n
]}
:
case
ch
<-
&
packet
{
srcAddr
:
addr
.
String
(),
dstAddr
:
raddr
.
String
()
,
data
:
b
[
:
n
]}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s -> %s : %s"
,
addr
,
raddr
,
"send queue is full, discard"
)
}
...
...
@@ -264,7 +262,12 @@ func (s *UdpForwardServer) ListenAndServe() error {
// start recv queue
go
func
(
ch
<-
chan
*
packet
)
{
for
pkt
:=
range
ch
{
if
_
,
err
:=
conn
.
WriteToUDP
(
pkt
.
data
,
pkt
.
dstAddr
);
err
!=
nil
{
dstAddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
pkt
.
dstAddr
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
continue
}
if
_
,
err
:=
conn
.
WriteToUDP
(
pkt
.
data
,
dstAddr
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
return
}
...
...
@@ -285,7 +288,7 @@ func (s *UdpForwardServer) ListenAndServe() error {
}
}
node
,
ok
:=
m
[
pkt
.
srcAddr
.
String
()
]
node
,
ok
:=
m
[
pkt
.
srcAddr
]
if
!
ok
{
node
=
&
cnode
{
chain
:
s
.
Base
.
Chain
,
...
...
@@ -295,7 +298,7 @@ func (s *UdpForwardServer) ListenAndServe() error {
wChan
:
make
(
chan
*
packet
,
32
),
ttl
:
time
.
Duration
(
s
.
TTL
)
*
time
.
Second
,
}
m
[
pkt
.
srcAddr
.
String
()
]
=
node
m
[
pkt
.
srcAddr
]
=
node
go
node
.
run
()
glog
.
V
(
LINFO
)
.
Infof
(
"[udp] %s -> %s : new client (%d)"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
len
(
m
))
}
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/gost.go
View file @
8861ffba
...
...
@@ -11,7 +11,7 @@ import (
)
const
(
Version
=
"2.
3
"
Version
=
"2.
4-dev
"
)
// Log level for glog
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/node.go
View file @
8861ffba
...
...
@@ -71,7 +71,7 @@ func ParseProxyNode(s string) (node ProxyNode, err error) {
}
switch
node
.
Transport
{
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"
ssu"
,
"quic"
,
"kcp"
,
"redirect
"
:
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"
quic"
,
"kcp"
,
"redirect"
,
"ssu
"
:
case
"https"
:
node
.
Protocol
=
"http"
node
.
Transport
=
"tls"
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/server.go
View file @
8861ffba
...
...
@@ -32,7 +32,7 @@ func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *Prox
var
cipher
*
ss
.
Cipher
var
ota
bool
if
node
.
Protocol
==
"ss"
{
if
node
.
Protocol
==
"ss"
||
node
.
Transport
==
"ssu"
{
var
err
error
var
method
,
password
string
...
...
@@ -98,8 +98,6 @@ func (s *ProxyServer) Serve() error {
return
NewRTcpForwardServer
(
s
)
.
Serve
()
case
"rudp"
:
// Remote UDP port forwarding
return
NewRUdpForwardServer
(
s
)
.
Serve
()
case
"ssu"
:
// TODO: shadowsocks udp relay
return
NewShadowUdpServer
(
s
)
.
ListenAndServe
()
case
"quic"
:
return
NewQuicServer
(
s
)
.
ListenAndServeTLS
(
s
.
TLSConfig
)
case
"kcp"
:
...
...
@@ -118,6 +116,12 @@ func (s *ProxyServer) Serve() error {
return
NewKCPServer
(
s
,
config
)
.
ListenAndServe
()
case
"redirect"
:
return
NewRedsocksTCPServer
(
s
)
.
ListenAndServe
()
case
"ssu"
:
// shadowsocks udp relay
ttl
,
_
:=
strconv
.
Atoi
(
s
.
Node
.
Get
(
"ttl"
))
if
ttl
<=
0
{
ttl
=
DefaultTTL
}
return
NewShadowUdpServer
(
s
,
ttl
)
.
ListenAndServe
()
default
:
ln
,
err
=
net
.
Listen
(
"tcp"
,
node
.
Addr
)
}
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/ss.go
View file @
8861ffba
...
...
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/ginuerzh/gosocks5"
"github.com/golang/glog"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
"io"
...
...
@@ -65,47 +66,6 @@ func (s *ShadowServer) Serve() {
glog
.
V
(
LINFO
)
.
Infof
(
"[ss] %s >-< %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
}
type
ShadowUdpServer
struct
{
Base
*
ProxyServer
Handler
func
(
conn
*
net
.
UDPConn
,
addr
*
net
.
UDPAddr
,
data
[]
byte
)
}
func
NewShadowUdpServer
(
base
*
ProxyServer
)
*
ShadowUdpServer
{
return
&
ShadowUdpServer
{
Base
:
base
}
}
func
(
s
*
ShadowUdpServer
)
ListenAndServe
()
error
{
laddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
s
.
Base
.
Node
.
Addr
)
if
err
!=
nil
{
return
err
}
lconn
,
err
:=
net
.
ListenUDP
(
"udp"
,
laddr
)
if
err
!=
nil
{
return
err
}
defer
lconn
.
Close
()
if
s
.
Handler
==
nil
{
s
.
Handler
=
s
.
HandleConn
}
for
{
b
:=
make
([]
byte
,
LargeBufferSize
)
n
,
addr
,
err
:=
lconn
.
ReadFromUDP
(
b
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
err
)
continue
}
go
s
.
Handler
(
lconn
,
addr
,
b
[
:
n
])
}
}
// TODO: shadowsocks udp relay handler
func
(
s
*
ShadowUdpServer
)
HandleConn
(
conn
*
net
.
UDPConn
,
addr
*
net
.
UDPAddr
,
data
[]
byte
)
{
}
// This function is copied from shadowsocks library with some modification.
func
(
s
*
ShadowServer
)
getRequest
()
(
host
string
,
ota
bool
,
err
error
)
{
// buf size should at least have the same size with the largest possible
...
...
@@ -276,3 +236,109 @@ func (c *shadowConn) SetReadDeadline(t time.Time) error {
func
(
c
*
shadowConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
type
ShadowUdpServer
struct
{
Base
*
ProxyServer
TTL
int
}
func
NewShadowUdpServer
(
base
*
ProxyServer
,
ttl
int
)
*
ShadowUdpServer
{
return
&
ShadowUdpServer
{
Base
:
base
,
TTL
:
ttl
}
}
func
(
s
*
ShadowUdpServer
)
ListenAndServe
()
error
{
laddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
s
.
Base
.
Node
.
Addr
)
if
err
!=
nil
{
return
err
}
lconn
,
err
:=
net
.
ListenUDP
(
"udp"
,
laddr
)
if
err
!=
nil
{
return
err
}
defer
lconn
.
Close
()
conn
:=
ss
.
NewSecurePacketConn
(
lconn
,
s
.
Base
.
cipher
.
Copy
(),
true
)
// force OTA on
rChan
,
wChan
:=
make
(
chan
*
packet
,
128
),
make
(
chan
*
packet
,
128
)
// start send queue
go
func
(
ch
chan
<-
*
packet
)
{
for
{
b
:=
make
([]
byte
,
MediumBufferSize
)
n
,
addr
,
err
:=
conn
.
ReadFrom
(
b
[
3
:
])
// add rsv and frag fields to make it the standard SOCKS5 UDP datagram
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
addr
,
laddr
,
err
)
continue
}
if
b
[
3
]
&
ss
.
OneTimeAuthMask
>
0
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : client does not support OTA"
,
addr
,
laddr
)
continue
}
b
[
3
]
&=
ss
.
AddrMask
dgram
,
err
:=
gosocks5
.
ReadUDPDatagram
(
bytes
.
NewReader
(
b
[
:
n
+
3
]))
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
addr
,
laddr
,
err
)
continue
}
select
{
case
ch
<-
&
packet
{
srcAddr
:
addr
.
String
(),
dstAddr
:
dgram
.
Header
.
Addr
.
String
(),
data
:
b
[
:
n
+
3
]}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
addr
,
dgram
.
Header
.
Addr
.
String
(),
"send queue is full, discard"
)
}
}
}(
wChan
)
// start recv queue
go
func
(
ch
<-
chan
*
packet
)
{
for
pkt
:=
range
ch
{
dstAddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
pkt
.
dstAddr
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
continue
}
if
_
,
err
:=
conn
.
WriteTo
(
pkt
.
data
,
dstAddr
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
return
}
}
}(
rChan
)
// mapping client to node
m
:=
make
(
map
[
string
]
*
cnode
)
// start dispatcher
for
pkt
:=
range
wChan
{
// clear obsolete nodes
for
k
,
node
:=
range
m
{
if
node
!=
nil
&&
node
.
err
!=
nil
{
close
(
node
.
wChan
)
delete
(
m
,
k
)
glog
.
V
(
LINFO
)
.
Infof
(
"[ssu] clear node %s"
,
k
)
}
}
node
,
ok
:=
m
[
pkt
.
srcAddr
]
if
!
ok
{
node
=
&
cnode
{
chain
:
s
.
Base
.
Chain
,
srcAddr
:
pkt
.
srcAddr
,
dstAddr
:
pkt
.
dstAddr
,
rChan
:
rChan
,
wChan
:
make
(
chan
*
packet
,
32
),
ttl
:
time
.
Duration
(
s
.
TTL
)
*
time
.
Second
,
}
m
[
pkt
.
srcAddr
]
=
node
go
node
.
run
()
glog
.
V
(
LINFO
)
.
Infof
(
"[ssu] %s -> %s : new client (%d)"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
len
(
m
))
}
select
{
case
node
.
wChan
<-
pkt
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
"node send queue is full, discard"
)
}
}
return
nil
}
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/encrypt.go
View file @
8861ffba
...
...
@@ -12,7 +12,7 @@ import (
"io"
"strings"
"github.com/
codahale
/chacha20"
"github.com/
Yawning
/chacha20"
"golang.org/x/crypto/blowfish"
"golang.org/x/crypto/cast5"
"golang.org/x/crypto/salsa20/salsa"
...
...
@@ -65,11 +65,19 @@ func newStream(block cipher.Block, err error, key, iv []byte,
}
}
func
newAESStream
(
key
,
iv
[]
byte
,
doe
DecOrEnc
)
(
cipher
.
Stream
,
error
)
{
func
newAES
CFB
Stream
(
key
,
iv
[]
byte
,
doe
DecOrEnc
)
(
cipher
.
Stream
,
error
)
{
block
,
err
:=
aes
.
NewCipher
(
key
)
return
newStream
(
block
,
err
,
key
,
iv
,
doe
)
}
func
newAESCTRStream
(
key
,
iv
[]
byte
,
doe
DecOrEnc
)
(
cipher
.
Stream
,
error
)
{
block
,
err
:=
aes
.
NewCipher
(
key
)
if
err
!=
nil
{
return
nil
,
err
}
return
cipher
.
NewCTR
(
block
,
iv
),
nil
}
func
newDESStream
(
key
,
iv
[]
byte
,
doe
DecOrEnc
)
(
cipher
.
Stream
,
error
)
{
block
,
err
:=
des
.
NewCipher
(
key
)
return
newStream
(
block
,
err
,
key
,
iv
,
doe
)
...
...
@@ -95,7 +103,11 @@ func newRC4MD5Stream(key, iv []byte, _ DecOrEnc) (cipher.Stream, error) {
}
func
newChaCha20Stream
(
key
,
iv
[]
byte
,
_
DecOrEnc
)
(
cipher
.
Stream
,
error
)
{
return
chacha20
.
New
(
key
,
iv
)
return
chacha20
.
NewCipher
(
key
,
iv
)
}
func
newChaCha20IETFStream
(
key
,
iv
[]
byte
,
_
DecOrEnc
)
(
cipher
.
Stream
,
error
)
{
return
chacha20
.
NewCipher
(
key
,
iv
)
}
type
salsaStreamCipher
struct
{
...
...
@@ -145,15 +157,19 @@ type cipherInfo struct {
}
var
cipherMethod
=
map
[
string
]
*
cipherInfo
{
"aes-128-cfb"
:
{
16
,
16
,
newAESStream
},
"aes-192-cfb"
:
{
24
,
16
,
newAESStream
},
"aes-256-cfb"
:
{
32
,
16
,
newAESStream
},
"des-cfb"
:
{
8
,
8
,
newDESStream
},
"bf-cfb"
:
{
16
,
8
,
newBlowFishStream
},
"cast5-cfb"
:
{
16
,
8
,
newCast5Stream
},
"rc4-md5"
:
{
16
,
16
,
newRC4MD5Stream
},
"chacha20"
:
{
32
,
8
,
newChaCha20Stream
},
"salsa20"
:
{
32
,
8
,
newSalsa20Stream
},
"aes-128-cfb"
:
{
16
,
16
,
newAESCFBStream
},
"aes-192-cfb"
:
{
24
,
16
,
newAESCFBStream
},
"aes-256-cfb"
:
{
32
,
16
,
newAESCFBStream
},
"aes-128-ctr"
:
{
16
,
16
,
newAESCTRStream
},
"aes-192-ctr"
:
{
24
,
16
,
newAESCTRStream
},
"aes-256-ctr"
:
{
32
,
16
,
newAESCTRStream
},
"des-cfb"
:
{
8
,
8
,
newDESStream
},
"bf-cfb"
:
{
16
,
8
,
newBlowFishStream
},
"cast5-cfb"
:
{
16
,
8
,
newCast5Stream
},
"rc4-md5"
:
{
16
,
16
,
newRC4MD5Stream
},
"chacha20"
:
{
32
,
8
,
newChaCha20Stream
},
"chacha20-ietf"
:
{
32
,
12
,
newChaCha20IETFStream
},
"salsa20"
:
{
32
,
8
,
newSalsa20Stream
},
}
func
CheckCipherMethod
(
method
string
)
error
{
...
...
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udp.go
0 → 100644
View file @
8861ffba
package
shadowsocks
import
(
"bytes"
"fmt"
"net"
"time"
)
const
(
maxPacketSize
=
4096
// increase it if error occurs
)
var
(
errPacketTooSmall
=
fmt
.
Errorf
(
"[udp]read error: cannot decrypt, received packet is smaller than ivLen"
)
errPacketTooLarge
=
fmt
.
Errorf
(
"[udp]read error: received packet is latger than maxPacketSize(%d)"
,
maxPacketSize
)
errBufferTooSmall
=
fmt
.
Errorf
(
"[udp]read error: given buffer is too small to hold data"
)
errPacketOtaFailed
=
fmt
.
Errorf
(
"[udp]read error: received packet has invalid ota"
)
)
type
SecurePacketConn
struct
{
net
.
PacketConn
*
Cipher
ota
bool
}
func
NewSecurePacketConn
(
c
net
.
PacketConn
,
cipher
*
Cipher
,
ota
bool
)
*
SecurePacketConn
{
return
&
SecurePacketConn
{
PacketConn
:
c
,
Cipher
:
cipher
,
ota
:
ota
,
}
}
func
(
c
*
SecurePacketConn
)
Close
()
error
{
return
c
.
PacketConn
.
Close
()
}
func
(
c
*
SecurePacketConn
)
ReadFrom
(
b
[]
byte
)
(
n
int
,
src
net
.
Addr
,
err
error
)
{
ota
:=
false
cipher
:=
c
.
Copy
()
buf
:=
make
([]
byte
,
4096
)
n
,
src
,
err
=
c
.
PacketConn
.
ReadFrom
(
buf
)
if
err
!=
nil
{
return
}
if
n
<
c
.
info
.
ivLen
{
return
0
,
nil
,
errPacketTooSmall
}
if
len
(
b
)
<
n
-
c
.
info
.
ivLen
{
err
=
errBufferTooSmall
// just a warning
}
iv
:=
make
([]
byte
,
c
.
info
.
ivLen
)
copy
(
iv
,
buf
[
:
c
.
info
.
ivLen
])
if
err
=
cipher
.
initDecrypt
(
iv
);
err
!=
nil
{
return
}
cipher
.
decrypt
(
b
[
0
:
],
buf
[
c
.
info
.
ivLen
:
n
])
n
-=
c
.
info
.
ivLen
if
b
[
idType
]
&
OneTimeAuthMask
>
0
{
ota
=
true
}
if
c
.
ota
&&
!
ota
{
return
0
,
src
,
errPacketOtaFailed
}
if
ota
{
key
:=
cipher
.
key
actualHmacSha1Buf
:=
HmacSha1
(
append
(
iv
,
key
...
),
b
[
:
n
-
lenHmacSha1
])
if
!
bytes
.
Equal
(
b
[
n
-
lenHmacSha1
:
n
],
actualHmacSha1Buf
)
{
Debug
.
Printf
(
"verify one time auth failed, iv=%v key=%v data=%v"
,
iv
,
key
,
b
)
return
0
,
src
,
errPacketOtaFailed
}
n
-=
lenHmacSha1
}
return
}
func
(
c
*
SecurePacketConn
)
WriteTo
(
b
[]
byte
,
dst
net
.
Addr
)
(
n
int
,
err
error
)
{
cipher
:=
c
.
Copy
()
iv
,
err
:=
cipher
.
initEncrypt
()
if
err
!=
nil
{
return
}
packetLen
:=
len
(
b
)
+
len
(
iv
)
if
c
.
ota
{
b
[
idType
]
|=
OneTimeAuthMask
packetLen
+=
lenHmacSha1
key
:=
cipher
.
key
actualHmacSha1Buf
:=
HmacSha1
(
append
(
iv
,
key
...
),
b
)
b
=
append
(
b
,
actualHmacSha1Buf
...
)
}
cipherData
:=
make
([]
byte
,
packetLen
)
copy
(
cipherData
,
iv
)
cipher
.
encrypt
(
cipherData
[
len
(
iv
)
:
],
b
)
n
,
err
=
c
.
PacketConn
.
WriteTo
(
cipherData
,
dst
)
if
c
.
ota
{
n
-=
lenHmacSha1
}
return
}
func
(
c
*
SecurePacketConn
)
LocalAddr
()
net
.
Addr
{
return
c
.
PacketConn
.
LocalAddr
()
}
func
(
c
*
SecurePacketConn
)
SetDeadline
(
t
time
.
Time
)
error
{
return
c
.
PacketConn
.
SetDeadline
(
t
)
}
func
(
c
*
SecurePacketConn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
return
c
.
PacketConn
.
SetReadDeadline
(
t
)
}
func
(
c
*
SecurePacketConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
PacketConn
.
SetWriteDeadline
(
t
)
}
func
(
c
*
SecurePacketConn
)
IsOta
()
bool
{
return
c
.
ota
}
func
(
c
*
SecurePacketConn
)
ForceOTA
()
net
.
PacketConn
{
return
NewSecurePacketConn
(
c
.
PacketConn
,
c
.
Cipher
.
Copy
(),
true
)
}
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/udprelay.go
0 → 100644
View file @
8861ffba
package
shadowsocks
import
(
"encoding/binary"
"fmt"
"net"
"strconv"
"strings"
"sync"
"syscall"
"time"
)
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
lenHmacSha1
=
10
)
var
(
reqList
=
newReqList
()
natlist
=
newNatTable
()
udpTimeout
=
30
*
time
.
Second
reqListRefreshTime
=
5
*
time
.
Minute
)
type
natTable
struct
{
sync
.
Mutex
conns
map
[
string
]
net
.
PacketConn
}
func
newNatTable
()
*
natTable
{
return
&
natTable
{
conns
:
map
[
string
]
net
.
PacketConn
{}}
}
func
(
table
*
natTable
)
Delete
(
index
string
)
net
.
PacketConn
{
table
.
Lock
()
defer
table
.
Unlock
()
c
,
ok
:=
table
.
conns
[
index
]
if
ok
{
delete
(
table
.
conns
,
index
)
return
c
}
return
nil
}
func
(
table
*
natTable
)
Get
(
index
string
)
(
c
net
.
PacketConn
,
ok
bool
,
err
error
)
{
table
.
Lock
()
defer
table
.
Unlock
()
c
,
ok
=
table
.
conns
[
index
]
if
!
ok
{
c
,
err
=
net
.
ListenPacket
(
"udp"
,
""
)
if
err
!=
nil
{
return
nil
,
false
,
err
}
table
.
conns
[
index
]
=
c
}
return
}
type
requestHeaderList
struct
{
sync
.
Mutex
List
map
[
string
]([]
byte
)
}
func
newReqList
()
*
requestHeaderList
{
ret
:=
&
requestHeaderList
{
List
:
map
[
string
]([]
byte
){}}
go
func
()
{
for
{
time
.
Sleep
(
reqListRefreshTime
)
ret
.
Refresh
()
}
}()
return
ret
}
func
(
r
*
requestHeaderList
)
Refresh
()
{
r
.
Lock
()
defer
r
.
Unlock
()
for
k
,
_
:=
range
r
.
List
{
delete
(
r
.
List
,
k
)
}
}
func
(
r
*
requestHeaderList
)
Get
(
dstaddr
string
)
(
req
[]
byte
,
ok
bool
)
{
r
.
Lock
()
defer
r
.
Unlock
()
req
,
ok
=
r
.
List
[
dstaddr
]
return
}
func
(
r
*
requestHeaderList
)
Put
(
dstaddr
string
,
req
[]
byte
)
{
r
.
Lock
()
defer
r
.
Unlock
()
r
.
List
[
dstaddr
]
=
req
return
}
func
parseHeaderFromAddr
(
addr
net
.
Addr
)
([]
byte
,
int
)
{
// if the request address type is domain, it cannot be reverselookuped
ip
,
port
,
err
:=
net
.
SplitHostPort
(
addr
.
String
())
if
err
!=
nil
{
return
nil
,
0
}
buf
:=
make
([]
byte
,
20
)
IP
:=
net
.
ParseIP
(
ip
)
b1
:=
IP
.
To4
()
iplen
:=
0
if
b1
==
nil
{
//ipv6
b1
=
IP
.
To16
()
buf
[
0
]
=
typeIPv6
iplen
=
net
.
IPv6len
}
else
{
//ipv4
buf
[
0
]
=
typeIPv4
iplen
=
net
.
IPv4len
}
copy
(
buf
[
1
:
],
b1
)
port_i
,
_
:=
strconv
.
Atoi
(
port
)
binary
.
BigEndian
.
PutUint16
(
buf
[
1
+
iplen
:
],
uint16
(
port_i
))
return
buf
[
:
1
+
iplen
+
2
],
1
+
iplen
+
2
}
func
Pipeloop
(
write
net
.
PacketConn
,
writeAddr
net
.
Addr
,
readClose
net
.
PacketConn
)
{
buf
:=
leakyBuf
.
Get
()
defer
leakyBuf
.
Put
(
buf
)
defer
readClose
.
Close
()
for
{
readClose
.
SetDeadline
(
time
.
Now
()
.
Add
(
udpTimeout
))
n
,
raddr
,
err
:=
readClose
.
ReadFrom
(
buf
)
if
err
!=
nil
{
if
ne
,
ok
:=
err
.
(
*
net
.
OpError
);
ok
{
if
ne
.
Err
==
syscall
.
EMFILE
||
ne
.
Err
==
syscall
.
ENFILE
{
// log too many open file error
// EMFILE is process reaches open file limits, ENFILE is system limit
Debug
.
Println
(
"[udp]read error:"
,
err
)
}
}
Debug
.
Printf
(
"[udp]closed pipe %s<-%s
\n
"
,
writeAddr
,
readClose
.
LocalAddr
())
return
}
// need improvement here
if
req
,
ok
:=
reqList
.
Get
(
raddr
.
String
());
ok
{
write
.
WriteTo
(
append
(
req
,
buf
[
:
n
]
...
),
writeAddr
)
}
else
{
header
,
hlen
:=
parseHeaderFromAddr
(
raddr
)
write
.
WriteTo
(
append
(
header
[
:
hlen
],
buf
[
:
n
]
...
),
writeAddr
)
}
}
}
func
handleUDPConnection
(
handle
*
SecurePacketConn
,
n
int
,
src
net
.
Addr
,
receive
[]
byte
)
{
var
dstIP
net
.
IP
var
reqLen
int
var
ota
bool
addrType
:=
receive
[
idType
]
defer
leakyBuf
.
Put
(
receive
)
if
addrType
&
OneTimeAuthMask
>
0
{
ota
=
true
}
receive
[
idType
]
&=
^
OneTimeAuthMask
compatiblemode
:=
!
handle
.
IsOta
()
&&
ota
switch
addrType
&
AddrMask
{
case
typeIPv4
:
reqLen
=
lenIPv4
if
len
(
receive
)
<
reqLen
{
Debug
.
Println
(
"[udp]invalid received message."
)
}
dstIP
=
net
.
IP
(
receive
[
idIP0
:
idIP0
+
net
.
IPv4len
])
case
typeIPv6
:
reqLen
=
lenIPv6
if
len
(
receive
)
<
reqLen
{
Debug
.
Println
(
"[udp]invalid received message."
)
}
dstIP
=
net
.
IP
(
receive
[
idIP0
:
idIP0
+
net
.
IPv6len
])
case
typeDm
:
reqLen
=
int
(
receive
[
idDmLen
])
+
lenDmBase
if
len
(
receive
)
<
reqLen
{
Debug
.
Println
(
"[udp]invalid received message."
)
}
name
:=
string
(
receive
[
idDm0
:
idDm0
+
int
(
receive
[
idDmLen
])])
// avoid panic: syscall: string with NUL passed to StringToUTF16 on windows.
if
strings
.
ContainsRune
(
name
,
0x00
)
{
fmt
.
Println
(
"[udp]invalid domain name."
)
return
}
dIP
,
err
:=
net
.
ResolveIPAddr
(
"ip"
,
name
)
// carefully with const type
if
err
!=
nil
{
Debug
.
Printf
(
"[udp]failed to resolve domain name: %s
\n
"
,
string
(
receive
[
idDm0
:
idDm0
+
receive
[
idDmLen
]]))
return
}
dstIP
=
dIP
.
IP
default
:
Debug
.
Printf
(
"[udp]addrType %d not supported"
,
addrType
)
return
}
dst
:=
&
net
.
UDPAddr
{
IP
:
dstIP
,
Port
:
int
(
binary
.
BigEndian
.
Uint16
(
receive
[
reqLen
-
2
:
reqLen
])),
}
if
_
,
ok
:=
reqList
.
Get
(
dst
.
String
());
!
ok
{
req
:=
make
([]
byte
,
reqLen
)
copy
(
req
,
receive
)
reqList
.
Put
(
dst
.
String
(),
req
)
}
remote
,
exist
,
err
:=
natlist
.
Get
(
src
.
String
())
if
err
!=
nil
{
return
}
if
!
exist
{
Debug
.
Printf
(
"[udp]new client %s->%s via %s ota=%v
\n
"
,
src
,
dst
,
remote
.
LocalAddr
(),
ota
)
go
func
()
{
if
compatiblemode
{
Pipeloop
(
handle
.
ForceOTA
(),
src
,
remote
)
}
else
{
Pipeloop
(
handle
,
src
,
remote
)
}
natlist
.
Delete
(
src
.
String
())
}()
}
else
{
Debug
.
Printf
(
"[udp]using cached client %s->%s via %s ota=%v
\n
"
,
src
,
dst
,
remote
.
LocalAddr
(),
ota
)
}
if
remote
==
nil
{
fmt
.
Println
(
"WTF"
)
}
remote
.
SetDeadline
(
time
.
Now
()
.
Add
(
udpTimeout
))
_
,
err
=
remote
.
WriteTo
(
receive
[
reqLen
:
n
],
dst
)
if
err
!=
nil
{
if
ne
,
ok
:=
err
.
(
*
net
.
OpError
);
ok
&&
(
ne
.
Err
==
syscall
.
EMFILE
||
ne
.
Err
==
syscall
.
ENFILE
)
{
// log too many open file error
// EMFILE is process reaches open file limits, ENFILE is system limit
Debug
.
Println
(
"[udp]write error:"
,
err
)
}
else
{
Debug
.
Println
(
"[udp]error connecting to:"
,
dst
,
err
)
}
if
conn
:=
natlist
.
Delete
(
src
.
String
());
conn
!=
nil
{
conn
.
Close
()
}
}
// Pipeloop
return
}
func
ReadAndHandleUDPReq
(
c
*
SecurePacketConn
)
error
{
buf
:=
leakyBuf
.
Get
()
n
,
src
,
err
:=
c
.
ReadFrom
(
buf
[
0
:
])
if
err
!=
nil
{
return
err
}
go
handleUDPConnection
(
c
,
n
,
src
,
buf
)
return
nil
}
cmd/gost/vendor/github.com/shadowsocks/shadowsocks-go/shadowsocks/util.go
View file @
8861ffba
package
shadowsocks
import
(
"errors"
"fmt"
"os"
"crypto/hmac"
"crypto/sha1"
"encoding/binary"
"errors"
"fmt"
"os"
)
func
PrintVersion
()
{
const
version
=
"1.
1.5
"
const
version
=
"1.
2.0
"
fmt
.
Println
(
"shadowsocks-go version"
,
version
)
}
...
...
@@ -57,4 +57,4 @@ func (flag *ClosedFlag) SetClosed() {
func
(
flag
*
ClosedFlag
)
IsClosed
()
bool
{
return
flag
.
flag
}
\ No newline at end of file
}
cmd/gost/vendor/vendor.json
View file @
8861ffba
...
...
@@ -2,6 +2,12 @@
"comment"
:
""
,
"ignore"
:
"test"
,
"package"
:
[
{
"checksumSHA1"
:
"IFJyJgPCjumDG37lEb0lyRBBGZE="
,
"path"
:
"github.com/Yawning/chacha20"
,
"revision"
:
"c91e78db502ff629614837aacb7aa4efa61c651a"
,
"revisionTime"
:
"2016-04-30T09:49:23Z"
},
{
"checksumSHA1"
:
"QPs3L3mjPoi+a9GJCjW8HhyJczM="
,
"path"
:
"github.com/codahale/chacha20"
,
...
...
@@ -15,10 +21,10 @@
"revisionTime"
:
"2017-01-19T05:34:58Z"
},
{
"checksumSHA1"
:
"
b0uHAM/lCGCJ9GeKfClvrMMWXQM
="
,
"checksumSHA1"
:
"
idpL1fpHpfntk74IVfWtkP1PMZs
="
,
"path"
:
"github.com/ginuerzh/gost"
,
"revision"
:
"3
58f57add6087d77b1d978e92e2f7c8073c2f544
"
,
"revisionTime"
:
"2017-01-21T03:1
4:59
Z"
"revision"
:
"3
21b03712af504981d35a47c50c2cfe4dd788a9d
"
,
"revisionTime"
:
"2017-01-21T03:1
6:33
Z"
},
{
"checksumSHA1"
:
"URsJa4y/sUUw/STmbeYx9EKqaYE="
,
...
...
@@ -153,10 +159,10 @@
"revisionTime"
:
"2016-10-02T05:25:12Z"
},
{
"checksumSHA1"
:
"
o0WHRL8mNIhfsoWlzhdJ8du6+C8
="
,
"checksumSHA1"
:
"
MRsfMrdZwnnCTfIzT3czcj0lb0s
="
,
"path"
:
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
,
"revision"
:
"
5c9897ecdf623f385ccb8c2c78e32c5256961b41
"
,
"revisionTime"
:
"201
6-06-15T15:25:08
Z"
"revision"
:
"
97a5c71f80ba5f5b3e549f14a619fe557ff4f3c9
"
,
"revisionTime"
:
"201
7-01-21T20:35:16
Z"
},
{
"checksumSHA1"
:
"JsJdKXhz87gWenMwBeejTOeNE7k="
,
...
...
forward.go
View file @
8861ffba
...
...
@@ -63,15 +63,15 @@ func (s *TcpForwardServer) handleTcpForward(conn net.Conn, raddr net.Addr) {
}
type
packet
struct
{
srcAddr
*
net
.
UDPAddr
// src address
dstAddr
*
net
.
UDPAddr
// dest address
srcAddr
string
// src address
dstAddr
string
// dest address
data
[]
byte
}
type
cnode
struct
{
chain
*
ProxyChain
conn
net
.
Conn
srcAddr
,
dstAddr
*
net
.
UDPAddr
srcAddr
,
dstAddr
string
rChan
,
wChan
chan
*
packet
err
error
ttl
time
.
Duration
...
...
@@ -146,13 +146,9 @@ func (node *cnode) run() {
timer
.
Reset
(
node
.
ttl
)
glog
.
V
(
LDEBUG
)
.
Infof
(
"[udp] %s <<< %s : length %d"
,
node
.
srcAddr
,
addr
,
n
)
if
node
.
dstAddr
.
String
()
!=
addr
.
String
()
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : dst-addr mismatch (%s)"
,
node
.
srcAddr
,
node
.
dstAddr
,
addr
)
break
}
select
{
// swap srcAddr with dstAddr
case
node
.
rChan
<-
&
packet
{
srcAddr
:
node
.
dstAddr
,
dstAddr
:
node
.
srcAddr
,
data
:
b
[
:
n
]}
:
case
node
.
rChan
<-
&
packet
{
srcAddr
:
addr
.
String
()
,
dstAddr
:
node
.
srcAddr
,
data
:
b
[
:
n
]}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : %s"
,
node
.
srcAddr
,
node
.
dstAddr
,
"recv queue is full, discard"
)
}
...
...
@@ -169,13 +165,9 @@ func (node *cnode) run() {
timer
.
Reset
(
node
.
ttl
)
glog
.
V
(
LDEBUG
)
.
Infof
(
"[udp-tun] %s <<< %s : length %d"
,
node
.
srcAddr
,
dgram
.
Header
.
Addr
.
String
(),
len
(
dgram
.
Data
))
if
dgram
.
Header
.
Addr
.
String
()
!=
node
.
dstAddr
.
String
()
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp-tun] %s <- %s : dst-addr mismatch (%s)"
,
node
.
srcAddr
,
node
.
dstAddr
,
dgram
.
Header
.
Addr
)
break
}
select
{
// swap srcAddr with dstAddr
case
node
.
rChan
<-
&
packet
{
srcAddr
:
node
.
dstAddr
,
dstAddr
:
node
.
srcAddr
,
data
:
dgram
.
Data
}
:
case
node
.
rChan
<-
&
packet
{
srcAddr
:
dgram
.
Header
.
Addr
.
String
()
,
dstAddr
:
node
.
srcAddr
,
data
:
dgram
.
Data
}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp-tun] %s <- %s : %s"
,
node
.
srcAddr
,
node
.
dstAddr
,
"recv queue is full, discard"
)
}
...
...
@@ -187,9 +179,15 @@ func (node *cnode) run() {
for
pkt
:=
range
node
.
wChan
{
timer
.
Reset
(
node
.
ttl
)
dstAddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
pkt
.
dstAddr
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
err
)
continue
}
switch
c
:=
node
.
conn
.
(
type
)
{
case
*
net
.
UDPConn
:
if
_
,
err
:=
c
.
WriteToUDP
(
pkt
.
data
,
pkt
.
dstAddr
);
err
!=
nil
{
if
_
,
err
:=
c
.
WriteToUDP
(
pkt
.
data
,
dstAddr
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
err
)
node
.
err
=
err
errChan
<-
err
...
...
@@ -198,7 +196,7 @@ func (node *cnode) run() {
glog
.
V
(
LDEBUG
)
.
Infof
(
"[udp] %s >>> %s : length %d"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
len
(
pkt
.
data
))
default
:
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
uint16
(
len
(
pkt
.
data
)),
0
,
ToSocksAddr
(
pkt
.
dstAddr
)),
pkt
.
data
)
dgram
:=
gosocks5
.
NewUDPDatagram
(
gosocks5
.
NewUDPHeader
(
uint16
(
len
(
pkt
.
data
)),
0
,
ToSocksAddr
(
dstAddr
)),
pkt
.
data
)
if
err
:=
dgram
.
Write
(
c
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp-tun] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
err
)
node
.
err
=
err
...
...
@@ -255,7 +253,7 @@ func (s *UdpForwardServer) ListenAndServe() error {
}
select
{
case
ch
<-
&
packet
{
srcAddr
:
addr
,
dstAddr
:
raddr
,
data
:
b
[
:
n
]}
:
case
ch
<-
&
packet
{
srcAddr
:
addr
.
String
(),
dstAddr
:
raddr
.
String
()
,
data
:
b
[
:
n
]}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s -> %s : %s"
,
addr
,
raddr
,
"send queue is full, discard"
)
}
...
...
@@ -264,7 +262,12 @@ func (s *UdpForwardServer) ListenAndServe() error {
// start recv queue
go
func
(
ch
<-
chan
*
packet
)
{
for
pkt
:=
range
ch
{
if
_
,
err
:=
conn
.
WriteToUDP
(
pkt
.
data
,
pkt
.
dstAddr
);
err
!=
nil
{
dstAddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
pkt
.
dstAddr
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
continue
}
if
_
,
err
:=
conn
.
WriteToUDP
(
pkt
.
data
,
dstAddr
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[udp] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
return
}
...
...
@@ -285,7 +288,7 @@ func (s *UdpForwardServer) ListenAndServe() error {
}
}
node
,
ok
:=
m
[
pkt
.
srcAddr
.
String
()
]
node
,
ok
:=
m
[
pkt
.
srcAddr
]
if
!
ok
{
node
=
&
cnode
{
chain
:
s
.
Base
.
Chain
,
...
...
@@ -295,7 +298,7 @@ func (s *UdpForwardServer) ListenAndServe() error {
wChan
:
make
(
chan
*
packet
,
32
),
ttl
:
time
.
Duration
(
s
.
TTL
)
*
time
.
Second
,
}
m
[
pkt
.
srcAddr
.
String
()
]
=
node
m
[
pkt
.
srcAddr
]
=
node
go
node
.
run
()
glog
.
V
(
LINFO
)
.
Infof
(
"[udp] %s -> %s : new client (%d)"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
len
(
m
))
}
...
...
gost.go
View file @
8861ffba
...
...
@@ -11,7 +11,7 @@ import (
)
const
(
Version
=
"2.
3
"
Version
=
"2.
4-dev
"
)
// Log level for glog
...
...
node.go
View file @
8861ffba
...
...
@@ -71,7 +71,7 @@ func ParseProxyNode(s string) (node ProxyNode, err error) {
}
switch
node
.
Transport
{
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"
ssu"
,
"quic"
,
"kcp"
,
"redirect
"
:
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"
quic"
,
"kcp"
,
"redirect"
,
"ssu
"
:
case
"https"
:
node
.
Protocol
=
"http"
node
.
Transport
=
"tls"
...
...
server.go
View file @
8861ffba
...
...
@@ -32,7 +32,7 @@ func NewProxyServer(node ProxyNode, chain *ProxyChain, config *tls.Config) *Prox
var
cipher
*
ss
.
Cipher
var
ota
bool
if
node
.
Protocol
==
"ss"
{
if
node
.
Protocol
==
"ss"
||
node
.
Transport
==
"ssu"
{
var
err
error
var
method
,
password
string
...
...
@@ -98,8 +98,6 @@ func (s *ProxyServer) Serve() error {
return
NewRTcpForwardServer
(
s
)
.
Serve
()
case
"rudp"
:
// Remote UDP port forwarding
return
NewRUdpForwardServer
(
s
)
.
Serve
()
case
"ssu"
:
// TODO: shadowsocks udp relay
return
NewShadowUdpServer
(
s
)
.
ListenAndServe
()
case
"quic"
:
return
NewQuicServer
(
s
)
.
ListenAndServeTLS
(
s
.
TLSConfig
)
case
"kcp"
:
...
...
@@ -118,6 +116,12 @@ func (s *ProxyServer) Serve() error {
return
NewKCPServer
(
s
,
config
)
.
ListenAndServe
()
case
"redirect"
:
return
NewRedsocksTCPServer
(
s
)
.
ListenAndServe
()
case
"ssu"
:
// shadowsocks udp relay
ttl
,
_
:=
strconv
.
Atoi
(
s
.
Node
.
Get
(
"ttl"
))
if
ttl
<=
0
{
ttl
=
DefaultTTL
}
return
NewShadowUdpServer
(
s
,
ttl
)
.
ListenAndServe
()
default
:
ln
,
err
=
net
.
Listen
(
"tcp"
,
node
.
Addr
)
}
...
...
ss.go
View file @
8861ffba
...
...
@@ -5,6 +5,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/ginuerzh/gosocks5"
"github.com/golang/glog"
ss
"github.com/shadowsocks/shadowsocks-go/shadowsocks"
"io"
...
...
@@ -65,47 +66,6 @@ func (s *ShadowServer) Serve() {
glog
.
V
(
LINFO
)
.
Infof
(
"[ss] %s >-< %s"
,
s
.
conn
.
RemoteAddr
(),
addr
)
}
type
ShadowUdpServer
struct
{
Base
*
ProxyServer
Handler
func
(
conn
*
net
.
UDPConn
,
addr
*
net
.
UDPAddr
,
data
[]
byte
)
}
func
NewShadowUdpServer
(
base
*
ProxyServer
)
*
ShadowUdpServer
{
return
&
ShadowUdpServer
{
Base
:
base
}
}
func
(
s
*
ShadowUdpServer
)
ListenAndServe
()
error
{
laddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
s
.
Base
.
Node
.
Addr
)
if
err
!=
nil
{
return
err
}
lconn
,
err
:=
net
.
ListenUDP
(
"udp"
,
laddr
)
if
err
!=
nil
{
return
err
}
defer
lconn
.
Close
()
if
s
.
Handler
==
nil
{
s
.
Handler
=
s
.
HandleConn
}
for
{
b
:=
make
([]
byte
,
LargeBufferSize
)
n
,
addr
,
err
:=
lconn
.
ReadFromUDP
(
b
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infoln
(
err
)
continue
}
go
s
.
Handler
(
lconn
,
addr
,
b
[
:
n
])
}
}
// TODO: shadowsocks udp relay handler
func
(
s
*
ShadowUdpServer
)
HandleConn
(
conn
*
net
.
UDPConn
,
addr
*
net
.
UDPAddr
,
data
[]
byte
)
{
}
// This function is copied from shadowsocks library with some modification.
func
(
s
*
ShadowServer
)
getRequest
()
(
host
string
,
ota
bool
,
err
error
)
{
// buf size should at least have the same size with the largest possible
...
...
@@ -276,3 +236,109 @@ func (c *shadowConn) SetReadDeadline(t time.Time) error {
func
(
c
*
shadowConn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
return
c
.
conn
.
SetWriteDeadline
(
t
)
}
type
ShadowUdpServer
struct
{
Base
*
ProxyServer
TTL
int
}
func
NewShadowUdpServer
(
base
*
ProxyServer
,
ttl
int
)
*
ShadowUdpServer
{
return
&
ShadowUdpServer
{
Base
:
base
,
TTL
:
ttl
}
}
func
(
s
*
ShadowUdpServer
)
ListenAndServe
()
error
{
laddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
s
.
Base
.
Node
.
Addr
)
if
err
!=
nil
{
return
err
}
lconn
,
err
:=
net
.
ListenUDP
(
"udp"
,
laddr
)
if
err
!=
nil
{
return
err
}
defer
lconn
.
Close
()
conn
:=
ss
.
NewSecurePacketConn
(
lconn
,
s
.
Base
.
cipher
.
Copy
(),
true
)
// force OTA on
rChan
,
wChan
:=
make
(
chan
*
packet
,
128
),
make
(
chan
*
packet
,
128
)
// start send queue
go
func
(
ch
chan
<-
*
packet
)
{
for
{
b
:=
make
([]
byte
,
MediumBufferSize
)
n
,
addr
,
err
:=
conn
.
ReadFrom
(
b
[
3
:
])
// add rsv and frag fields to make it the standard SOCKS5 UDP datagram
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
addr
,
laddr
,
err
)
continue
}
if
b
[
3
]
&
ss
.
OneTimeAuthMask
>
0
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : client does not support OTA"
,
addr
,
laddr
)
continue
}
b
[
3
]
&=
ss
.
AddrMask
dgram
,
err
:=
gosocks5
.
ReadUDPDatagram
(
bytes
.
NewReader
(
b
[
:
n
+
3
]))
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
addr
,
laddr
,
err
)
continue
}
select
{
case
ch
<-
&
packet
{
srcAddr
:
addr
.
String
(),
dstAddr
:
dgram
.
Header
.
Addr
.
String
(),
data
:
b
[
:
n
+
3
]}
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
addr
,
dgram
.
Header
.
Addr
.
String
(),
"send queue is full, discard"
)
}
}
}(
wChan
)
// start recv queue
go
func
(
ch
<-
chan
*
packet
)
{
for
pkt
:=
range
ch
{
dstAddr
,
err
:=
net
.
ResolveUDPAddr
(
"udp"
,
pkt
.
dstAddr
)
if
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
continue
}
if
_
,
err
:=
conn
.
WriteTo
(
pkt
.
data
,
dstAddr
);
err
!=
nil
{
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s <- %s : %s"
,
pkt
.
dstAddr
,
pkt
.
srcAddr
,
err
)
return
}
}
}(
rChan
)
// mapping client to node
m
:=
make
(
map
[
string
]
*
cnode
)
// start dispatcher
for
pkt
:=
range
wChan
{
// clear obsolete nodes
for
k
,
node
:=
range
m
{
if
node
!=
nil
&&
node
.
err
!=
nil
{
close
(
node
.
wChan
)
delete
(
m
,
k
)
glog
.
V
(
LINFO
)
.
Infof
(
"[ssu] clear node %s"
,
k
)
}
}
node
,
ok
:=
m
[
pkt
.
srcAddr
]
if
!
ok
{
node
=
&
cnode
{
chain
:
s
.
Base
.
Chain
,
srcAddr
:
pkt
.
srcAddr
,
dstAddr
:
pkt
.
dstAddr
,
rChan
:
rChan
,
wChan
:
make
(
chan
*
packet
,
32
),
ttl
:
time
.
Duration
(
s
.
TTL
)
*
time
.
Second
,
}
m
[
pkt
.
srcAddr
]
=
node
go
node
.
run
()
glog
.
V
(
LINFO
)
.
Infof
(
"[ssu] %s -> %s : new client (%d)"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
len
(
m
))
}
select
{
case
node
.
wChan
<-
pkt
:
case
<-
time
.
After
(
time
.
Second
*
3
)
:
glog
.
V
(
LWARNING
)
.
Infof
(
"[ssu] %s -> %s : %s"
,
pkt
.
srcAddr
,
pkt
.
dstAddr
,
"node send queue is full, discard"
)
}
}
return
nil
}
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