Skip to content

Commit 4f192ef

Browse files
committed
Init: first commit 🎉
1 parent 8532718 commit 4f192ef

27 files changed

+1451
-0
lines changed

‎.gitignore‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
8+
# Test binary, build with `go test -c`
9+
*.test
10+
11+
# Output of the go coverage tool, specifically when used with LiteIDE
12+
*.out
13+
14+
# dep
15+
vendor

‎Gopkg.lock‎

Lines changed: 84 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Gopkg.toml‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Gopkg.toml example
2+
#
3+
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
4+
# for detailed Gopkg.toml documentation.
5+
#
6+
# required = ["github.com/user/thing/cmd/thing"]
7+
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8+
#
9+
# [[constraint]]
10+
# name = "github.com/user/project"
11+
# version = "1.0.0"
12+
#
13+
# [[constraint]]
14+
# name = "github.com/user/project2"
15+
# branch = "dev"
16+
# source = "github.com/myfork/project2"
17+
#
18+
# [[override]]
19+
# name = "github.com/x/y"
20+
# version = "2.4.0"
21+
#
22+
# [prune]
23+
# non-go = false
24+
# go-tests = true
25+
# unused-packages = true
26+
27+
28+
[[constraint]]
29+
name = "github.com/oschwald/geoip2-golang"
30+
version = "1.2.1"
31+
32+
[[constraint]]
33+
name = "github.com/riobard/go-shadowsocks2"
34+
version = "0.1.0"
35+
36+
[[constraint]]
37+
name = "github.com/sirupsen/logrus"
38+
version = "1.0.5"
39+
40+
[[constraint]]
41+
name = "gopkg.in/eapache/channels.v1"
42+
version = "1.1.0"
43+
44+
[[constraint]]
45+
name = "gopkg.in/ini.v1"
46+
version = "1.37.0"
47+
48+
[prune]
49+
go-tests = true
50+
unused-packages = true

‎README.md‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Clash
2+
3+
A rule based proxy in Go.
4+
5+
## Features
6+
7+
- HTTP/HTTPS and SOCKS proxy
8+
- Surge like configuration
9+
- GeoIP rule support
10+
11+
## Install
12+
13+
You can build from source:
14+
15+
```sh
16+
go get -u -v github.com/Dreamacro/clash
17+
```
18+
19+
Requires Go >= 1.10.
20+
21+
## Config
22+
23+
Configuration file at `$HOME/.config/clash/config.ini`
24+
25+
Below is a simple demo configuration file:
26+
27+
```ini
28+
[General]
29+
port = 7890
30+
socks-port = 7891
31+
32+
[Proxy]
33+
# name = ss, server, port, cipter, password
34+
Proxy = ss, server, port, AEAD_CHACHA20_POLY1305, password
35+
36+
[Rule]
37+
DOMAIN-SUFFIX,google.com,Proxy
38+
DOMAIN-KEYWORD,google,Proxy
39+
DOMAIN-SUFFIX,ad.com,REJECT
40+
GEOIP,CN,DIRECT
41+
FINAL,,Proxy
42+
```
43+
44+
## TODO
45+
46+
- [ ] Complementing the necessary rule operators

‎adapters/direct.go‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package adapters
2+
3+
import (
4+
"io"
5+
"net"
6+
7+
C "github.com/Dreamacro/clash/constant"
8+
)
9+
10+
// DirectAdapter is a directly connected adapter
11+
type DirectAdapter struct {
12+
conn net.Conn
13+
}
14+
15+
// Writer is used to output network traffic
16+
func (d *DirectAdapter) Writer() io.Writer {
17+
return d.conn
18+
}
19+
20+
// Reader is used to input network traffic
21+
func (d *DirectAdapter) Reader() io.Reader {
22+
return d.conn
23+
}
24+
25+
// Close is used to close connection
26+
func (d *DirectAdapter) Close() {
27+
d.conn.Close()
28+
}
29+
30+
type Direct struct {
31+
}
32+
33+
func (d *Direct) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
34+
c, err := net.Dial("tcp", net.JoinHostPort(addr.Host, addr.Port))
35+
if err != nil {
36+
return
37+
}
38+
c.(*net.TCPConn).SetKeepAlive(true)
39+
return &DirectAdapter{conn: c}, nil
40+
}
41+
42+
func NewDirect() *Direct {
43+
return &Direct{}
44+
}

‎adapters/reject.go‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package adapters
2+
3+
import (
4+
"io"
5+
6+
C "github.com/Dreamacro/clash/constant"
7+
)
8+
9+
// RejectAdapter is a reject connected adapter
10+
type RejectAdapter struct {
11+
}
12+
13+
// Writer is used to output network traffic
14+
func (r *RejectAdapter) Writer() io.Writer {
15+
return &NopRW{}
16+
}
17+
18+
// Reader is used to input network traffic
19+
func (r *RejectAdapter) Reader() io.Reader {
20+
return &NopRW{}
21+
}
22+
23+
// Close is used to close connection
24+
func (r *RejectAdapter) Close() {
25+
}
26+
27+
type Reject struct {
28+
}
29+
30+
func (r *Reject) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
31+
return &RejectAdapter{}, nil
32+
}
33+
34+
func NewReject() *Reject {
35+
return &Reject{}
36+
}
37+
38+
type NopRW struct{}
39+
40+
func (rw *NopRW) Read(b []byte) (int, error) {
41+
return len(b), nil
42+
}
43+
44+
func (rw *NopRW) Write(b []byte) (int, error) {
45+
return 0, io.EOF
46+
}

‎adapters/shadowsocks.go‎

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package adapters
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"net"
8+
"net/url"
9+
"strconv"
10+
11+
C "github.com/Dreamacro/clash/constant"
12+
13+
"github.com/riobard/go-shadowsocks2/core"
14+
"github.com/riobard/go-shadowsocks2/socks"
15+
)
16+
17+
// ShadowsocksAdapter is a shadowsocks adapter
18+
type ShadowsocksAdapter struct {
19+
conn net.Conn
20+
}
21+
22+
// Writer is used to output network traffic
23+
func (ss *ShadowsocksAdapter) Writer() io.Writer {
24+
return ss.conn
25+
}
26+
27+
// Reader is used to input network traffic
28+
func (ss *ShadowsocksAdapter) Reader() io.Reader {
29+
return ss.conn
30+
}
31+
32+
// Close is used to close connection
33+
func (ss *ShadowsocksAdapter) Close() {
34+
ss.conn.Close()
35+
}
36+
37+
type ShadowSocks struct {
38+
server string
39+
cipher string
40+
password string
41+
}
42+
43+
func (ss *ShadowSocks) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
44+
var key []byte
45+
ciph, _ := core.PickCipher(ss.cipher, key, ss.password)
46+
c, err := net.Dial("tcp", ss.server)
47+
if err != nil {
48+
return nil, fmt.Errorf("%s connect error", ss.server)
49+
}
50+
c.(*net.TCPConn).SetKeepAlive(true)
51+
c = ciph.StreamConn(c)
52+
_, err = c.Write(serializesSocksAddr(addr))
53+
return &ShadowsocksAdapter{conn: c}, err
54+
}
55+
56+
func NewShadowSocks(ssURL string) *ShadowSocks {
57+
server, cipher, password, _ := parseURL(ssURL)
58+
return &ShadowSocks{
59+
server: server,
60+
cipher: cipher,
61+
password: password,
62+
}
63+
}
64+
65+
func parseURL(s string) (addr, cipher, password string, err error) {
66+
u, err := url.Parse(s)
67+
if err != nil {
68+
return
69+
}
70+
71+
addr = u.Host
72+
if u.User != nil {
73+
cipher = u.User.Username()
74+
password, _ = u.User.Password()
75+
}
76+
return
77+
}
78+
79+
func serializesSocksAddr(addr *C.Addr) []byte {
80+
var buf [][]byte
81+
aType := uint8(addr.AddrType)
82+
p, _ := strconv.Atoi(addr.Port)
83+
port := []byte{uint8(p >> 8), uint8(p & 0xff)}
84+
switch addr.AddrType {
85+
case socks.AtypDomainName:
86+
len := uint8(len(addr.Host))
87+
host := []byte(addr.Host)
88+
buf = [][]byte{[]byte{aType, len}, host, port}
89+
case socks.AtypIPv4:
90+
host := net.ParseIP(addr.Host).To4()
91+
buf = [][]byte{[]byte{aType}, host, port}
92+
case socks.AtypIPv6:
93+
host := net.ParseIP(addr.Host).To16()
94+
buf = [][]byte{[]byte{aType}, host, port}
95+
}
96+
return bytes.Join(buf, []byte(""))
97+
}

0 commit comments

Comments
 (0)