Init: first commit 🎉
This commit is contained in:
44
adapters/direct.go
Normal file
44
adapters/direct.go
Normal file
@ -0,0 +1,44 @@
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// DirectAdapter is a directly connected adapter
|
||||
type DirectAdapter struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
// Writer is used to output network traffic
|
||||
func (d *DirectAdapter) Writer() io.Writer {
|
||||
return d.conn
|
||||
}
|
||||
|
||||
// Reader is used to input network traffic
|
||||
func (d *DirectAdapter) Reader() io.Reader {
|
||||
return d.conn
|
||||
}
|
||||
|
||||
// Close is used to close connection
|
||||
func (d *DirectAdapter) Close() {
|
||||
d.conn.Close()
|
||||
}
|
||||
|
||||
type Direct struct {
|
||||
}
|
||||
|
||||
func (d *Direct) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
|
||||
c, err := net.Dial("tcp", net.JoinHostPort(addr.Host, addr.Port))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.(*net.TCPConn).SetKeepAlive(true)
|
||||
return &DirectAdapter{conn: c}, nil
|
||||
}
|
||||
|
||||
func NewDirect() *Direct {
|
||||
return &Direct{}
|
||||
}
|
46
adapters/reject.go
Normal file
46
adapters/reject.go
Normal file
@ -0,0 +1,46 @@
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
// RejectAdapter is a reject connected adapter
|
||||
type RejectAdapter struct {
|
||||
}
|
||||
|
||||
// Writer is used to output network traffic
|
||||
func (r *RejectAdapter) Writer() io.Writer {
|
||||
return &NopRW{}
|
||||
}
|
||||
|
||||
// Reader is used to input network traffic
|
||||
func (r *RejectAdapter) Reader() io.Reader {
|
||||
return &NopRW{}
|
||||
}
|
||||
|
||||
// Close is used to close connection
|
||||
func (r *RejectAdapter) Close() {
|
||||
}
|
||||
|
||||
type Reject struct {
|
||||
}
|
||||
|
||||
func (r *Reject) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
|
||||
return &RejectAdapter{}, nil
|
||||
}
|
||||
|
||||
func NewReject() *Reject {
|
||||
return &Reject{}
|
||||
}
|
||||
|
||||
type NopRW struct{}
|
||||
|
||||
func (rw *NopRW) Read(b []byte) (int, error) {
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (rw *NopRW) Write(b []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
97
adapters/shadowsocks.go
Normal file
97
adapters/shadowsocks.go
Normal file
@ -0,0 +1,97 @@
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
||||
"github.com/riobard/go-shadowsocks2/core"
|
||||
"github.com/riobard/go-shadowsocks2/socks"
|
||||
)
|
||||
|
||||
// ShadowsocksAdapter is a shadowsocks adapter
|
||||
type ShadowsocksAdapter struct {
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
// Writer is used to output network traffic
|
||||
func (ss *ShadowsocksAdapter) Writer() io.Writer {
|
||||
return ss.conn
|
||||
}
|
||||
|
||||
// Reader is used to input network traffic
|
||||
func (ss *ShadowsocksAdapter) Reader() io.Reader {
|
||||
return ss.conn
|
||||
}
|
||||
|
||||
// Close is used to close connection
|
||||
func (ss *ShadowsocksAdapter) Close() {
|
||||
ss.conn.Close()
|
||||
}
|
||||
|
||||
type ShadowSocks struct {
|
||||
server string
|
||||
cipher string
|
||||
password string
|
||||
}
|
||||
|
||||
func (ss *ShadowSocks) Generator(addr *C.Addr) (adapter C.ProxyAdapter, err error) {
|
||||
var key []byte
|
||||
ciph, _ := core.PickCipher(ss.cipher, key, ss.password)
|
||||
c, err := net.Dial("tcp", ss.server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error", ss.server)
|
||||
}
|
||||
c.(*net.TCPConn).SetKeepAlive(true)
|
||||
c = ciph.StreamConn(c)
|
||||
_, err = c.Write(serializesSocksAddr(addr))
|
||||
return &ShadowsocksAdapter{conn: c}, err
|
||||
}
|
||||
|
||||
func NewShadowSocks(ssURL string) *ShadowSocks {
|
||||
server, cipher, password, _ := parseURL(ssURL)
|
||||
return &ShadowSocks{
|
||||
server: server,
|
||||
cipher: cipher,
|
||||
password: password,
|
||||
}
|
||||
}
|
||||
|
||||
func parseURL(s string) (addr, cipher, password string, err error) {
|
||||
u, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
addr = u.Host
|
||||
if u.User != nil {
|
||||
cipher = u.User.Username()
|
||||
password, _ = u.User.Password()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func serializesSocksAddr(addr *C.Addr) []byte {
|
||||
var buf [][]byte
|
||||
aType := uint8(addr.AddrType)
|
||||
p, _ := strconv.Atoi(addr.Port)
|
||||
port := []byte{uint8(p >> 8), uint8(p & 0xff)}
|
||||
switch addr.AddrType {
|
||||
case socks.AtypDomainName:
|
||||
len := uint8(len(addr.Host))
|
||||
host := []byte(addr.Host)
|
||||
buf = [][]byte{[]byte{aType, len}, host, port}
|
||||
case socks.AtypIPv4:
|
||||
host := net.ParseIP(addr.Host).To4()
|
||||
buf = [][]byte{[]byte{aType}, host, port}
|
||||
case socks.AtypIPv6:
|
||||
host := net.ParseIP(addr.Host).To16()
|
||||
buf = [][]byte{[]byte{aType}, host, port}
|
||||
}
|
||||
return bytes.Join(buf, []byte(""))
|
||||
}
|
Reference in New Issue
Block a user