mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
trojan: added udp support
This commit is contained in:
parent
2520a1c8b4
commit
bfcf9272dc
79
README.md
79
README.md
@ -15,58 +15,26 @@ we can set up local listeners as proxy servers, and forward requests to internet
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
Listen (local proxy server):
|
||||
|
||||
- Socks5 proxy(tcp&udp)
|
||||
- Http proxy(tcp)
|
||||
- SS proxy(tcp&udp)
|
||||
- Linux transparent proxy(iptables redirect)
|
||||
- TCP tunnel
|
||||
- UDP tunnel
|
||||
- UDP over TCP tunnel
|
||||
- TLS, use it together with above proxy protocols(tcp)
|
||||
- Unix domain socket, use it together with above proxy protocols(tcp)
|
||||
- KCP protocol, use it together with above proxy protocols(tcp)
|
||||
|
||||
Forward (local proxy client/upstream proxy server):
|
||||
|
||||
- Socks5 proxy(tcp&udp)
|
||||
- Http proxy(tcp)
|
||||
- SS proxy(tcp&udp&uot)
|
||||
- SSR proxy(tcp)
|
||||
- VMess proxy(tcp)
|
||||
- Trojan proxy(tcp)
|
||||
- TLS, use it together with above proxy protocols(tcp)
|
||||
- Websocket, use it together with above proxy protocols(tcp)
|
||||
- Unix domain socket, use it together with above proxy protocols(tcp)
|
||||
- KCP protocol, use it together with above proxy protocols(tcp)
|
||||
- Simple-Obfs, use it together with above proxy protocols(tcp)
|
||||
|
||||
DNS Forwarding Server (udp2tcp):
|
||||
|
||||
- DNS Over Proxy
|
||||
- Listen on UDP and forward dns requests to remote dns server in TCP via forwarders
|
||||
- Specify different upstream dns server based on destinations(in rule file)
|
||||
- Tunnel mode: forward to a fixed upstream dns server
|
||||
- Add resolved IPs to proxy rules
|
||||
- Add resolved IPs to ipset
|
||||
- DNS cache
|
||||
- Custom dns record
|
||||
|
||||
IPSet Management (Linux kernel version >= 2.6.32):
|
||||
|
||||
- Add ip/cidrs from rule files on startup
|
||||
- Add resolved ips for domains from rule files by dns forwarding server
|
||||
|
||||
General:
|
||||
|
||||
- Proxy Server( -listen )
|
||||
- Proxy Client( -forward )
|
||||
- Http and socks5 on the same port
|
||||
- Forwarder chain
|
||||
- RR/HA/LHA/DH strategy for multiple forwarders
|
||||
- Periodical proxy checking
|
||||
- Rule proxy based on destinations: [Config Examples](config/examples)
|
||||
- Send requests from specific ip/interface
|
||||
- DNS Forwarding Server:
|
||||
- DNS Over Proxy
|
||||
- Listen on UDP and forward dns requests to remote dns server in TCP via forwarders
|
||||
- Specify different upstream dns server based on destinations(in rule file)
|
||||
- Tunnel mode: forward to a fixed upstream dns server
|
||||
- Add resolved IPs to proxy rules
|
||||
- Add resolved IPs to ipset
|
||||
- DNS cache
|
||||
- Custom dns record
|
||||
- IPSet Management (Linux kernel version >= 2.6.32):
|
||||
- Add ip/cidrs from rule files on startup
|
||||
- Add resolved ips for domains from rule files by dns forwarding server
|
||||
|
||||
TODO:
|
||||
|
||||
@ -76,6 +44,25 @@ TODO:
|
||||
- [ ] TUN/TAP device support
|
||||
- [ ] SSH tunnel support (maybe)
|
||||
|
||||
### Protocols
|
||||
Protocol | Listen/TCP | Listen/UDP | Forward/TCP | Forward/UDP
|
||||
-|-|-|-|-
|
||||
Socks5 | √ | √ | √ | √
|
||||
Http | √ | | √ |
|
||||
SS | √ | √ | √ | √
|
||||
Redir | √ | | |
|
||||
Tcptun | √ | | |
|
||||
Udptun | | √ | |
|
||||
UoTtun | | √ | |
|
||||
TLS | √ | | √ |
|
||||
Unix | √ | | √ |
|
||||
KCP | | √ | √ |
|
||||
SSR | | | √ |
|
||||
VMess | | | √ |
|
||||
Trojan | | | √ | √
|
||||
WebSocket | | | √ |
|
||||
Simple-Obfs | | | √ |
|
||||
|
||||
## Install
|
||||
|
||||
Binary:
|
||||
|
@ -13,26 +13,22 @@ const (
|
||||
AuthPassword = 2
|
||||
)
|
||||
|
||||
// SOCKS request commands as defined in RFC 1928 section 4.
|
||||
// SOCKS request commands as defined in RFC 1928 section 4
|
||||
const (
|
||||
CmdConnect = 1
|
||||
CmdBind = 2
|
||||
CmdUDPAssociate = 3
|
||||
CmdConnect byte = 1
|
||||
CmdBind byte = 2
|
||||
CmdUDPAssociate byte = 3
|
||||
)
|
||||
|
||||
// SOCKS address types as defined in RFC 1928 section 5.
|
||||
// SOCKS address types as defined in RFC 1928 section 5
|
||||
const (
|
||||
ATypIP4 = 1
|
||||
ATypDomain = 3
|
||||
ATypIP6 = 4
|
||||
)
|
||||
|
||||
const (
|
||||
// maximum size of SOCKS address in bytes.
|
||||
MaxAddrLen = 1 + 1 + 255 + 2
|
||||
// minimum size of SOCKS address in bytes.
|
||||
MinAddrLen = 5
|
||||
)
|
||||
// MaxAddrLen is the maximum size of SOCKS address in bytes
|
||||
const MaxAddrLen = 1 + 1 + 255 + 2
|
||||
|
||||
// Errors are socks5 errors
|
||||
var Errors = []error{
|
||||
|
@ -58,7 +58,7 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
return n, raddr, err
|
||||
}
|
||||
|
||||
if n < socks.MinAddrLen {
|
||||
if n < 3 {
|
||||
return n, raddr, errors.New("not enough size to get addr")
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,6 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
return n, raddr, err
|
||||
}
|
||||
|
||||
if n < socks.MinAddrLen {
|
||||
return n, raddr, errors.New("not enough size to get addr")
|
||||
}
|
||||
|
||||
tgtAddr := socks.SplitAddr(buf)
|
||||
if tgtAddr == nil {
|
||||
return n, raddr, errors.New("can not get addr")
|
||||
|
75
proxy/trojan/packet.go
Normal file
75
proxy/trojan/packet.go
Normal file
@ -0,0 +1,75 @@
|
||||
// https://trojan-gfw.github.io/trojan/protocol
|
||||
// If the connection is a UDP ASSOCIATE, then each UDP packet has the following format:
|
||||
// +------+----------+----------+--------+---------+----------+
|
||||
// | ATYP | DST.ADDR | DST.PORT | Length | CRLF | Payload |
|
||||
// +------+----------+----------+--------+---------+----------+
|
||||
// | 1 | Variable | 2 | 2 | X'0D0A' | Variable |
|
||||
// +------+----------+----------+--------+---------+----------+
|
||||
package trojan
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/nadoo/glider/common/conn"
|
||||
"github.com/nadoo/glider/common/socks"
|
||||
)
|
||||
|
||||
// PktConn .
|
||||
type PktConn struct {
|
||||
net.Conn
|
||||
|
||||
tgtAddr socks.Addr
|
||||
}
|
||||
|
||||
func NewPktConn(c net.Conn, tgtAddr socks.Addr) *PktConn {
|
||||
pc := &PktConn{
|
||||
Conn: c,
|
||||
tgtAddr: tgtAddr,
|
||||
}
|
||||
return pc
|
||||
}
|
||||
|
||||
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
// ATYP, DST.ADDR, DST.PORT
|
||||
_, err := socks.ReadAddr(pc.Conn)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// Length
|
||||
if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
length := int(binary.BigEndian.Uint16(b[:2]))
|
||||
if length > conn.UDPBufSize {
|
||||
return 0, nil, errors.New("packet invalid")
|
||||
}
|
||||
|
||||
// CRLF
|
||||
if _, err = io.ReadFull(pc.Conn, b[:2]); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// Payload
|
||||
n, err := io.ReadFull(pc.Conn, b[:length])
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// TODO: check the addr in return value, it's a fake packetConn so the addr is not valid
|
||||
return n, nil, err
|
||||
}
|
||||
|
||||
func (pc *PktConn) WriteTo(b []byte, addr net.Addr) (int, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.Write(pc.tgtAddr)
|
||||
binary.Write(&buf, binary.BigEndian, uint16(len(b)))
|
||||
buf.WriteString("\r\n")
|
||||
buf.Write(b)
|
||||
return pc.Write(buf.Bytes())
|
||||
}
|
@ -32,7 +32,6 @@ import (
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -42,7 +41,7 @@ import (
|
||||
"github.com/nadoo/glider/proxy"
|
||||
)
|
||||
|
||||
// Trojan is a base trojan struct.
|
||||
// Trojan is a base trojan struct
|
||||
type Trojan struct {
|
||||
dialer proxy.Dialer
|
||||
proxy proxy.Proxy
|
||||
@ -115,8 +114,13 @@ func (s *Trojan) Addr() string {
|
||||
|
||||
// Dial connects to the address addr on the network net via the proxy.
|
||||
func (s *Trojan) Dial(network, addr string) (net.Conn, error) {
|
||||
return s.dial(network, addr)
|
||||
}
|
||||
|
||||
func (s *Trojan) dial(network, addr string) (net.Conn, error) {
|
||||
rc, err := s.dialer.Dial("tcp", s.addr)
|
||||
if err != nil {
|
||||
log.F("[trojan]: dial to %s error: %s", s.addr, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -128,14 +132,28 @@ func (s *Trojan) Dial(network, addr string) (net.Conn, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.Write(s.pass[:])
|
||||
buf.WriteString("\r\n")
|
||||
buf.WriteByte(socks.CmdConnect)
|
||||
|
||||
cmd := socks.CmdConnect
|
||||
if network == "udp" {
|
||||
cmd = socks.CmdUDPAssociate
|
||||
}
|
||||
buf.WriteByte(cmd)
|
||||
|
||||
buf.Write(socks.ParseAddr(addr))
|
||||
buf.WriteString("\r\n")
|
||||
_, err = tlsConn.Write(buf.Bytes())
|
||||
|
||||
return tlsConn, err
|
||||
}
|
||||
|
||||
// DialUDP connects to the given address via the proxy.
|
||||
func (s *Trojan) DialUDP(network, addr string) (net.PacketConn, net.Addr, error) {
|
||||
return nil, nil, errors.New("trojan client does not support udp now")
|
||||
c, err := s.dial("udp", addr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
pkc := NewPktConn(c, socks.ParseAddr(addr))
|
||||
|
||||
return pkc, nil, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user