diff --git a/README.md b/README.md index 1aeb55144..dc2ec557c 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ [![License](https://img.shields.io/github/license/p4gefau1t/trojan-go)](https://img.shields.io/github/license/p4gefau1t/trojan-go) [![Downloads](https://img.shields.io/github/downloads/p4gefau1t/trojan-go/total?label=downloads&logo=github&style=flat-square)](https://img.shields.io/github/downloads/p4gefau1t/trojan-go/total?label=downloads&logo=github&style=flat-square) [![HitCounts](http://hits.dwyl.io/p4gefau1t/trojan-go.svg)](http://hits.dwyl.io/p4gefau1t/trojan-go) - [![Release](https://img.shields.io/github/v/release/p4gefau1t/trojan-go?include_prereleases)](https://img.shields.io/github/v/release/p4gefau1t/trojan-go?include_prereleases) [![Release Date](https://img.shields.io/github/release-date-pre/p4gefau1t/trojan-go)](https://img.shields.io/github/release-date-pre/p4gefau1t/trojan-go) [![Docker Image](https://images.microbadger.com/badges/image/p4gefau1t/trojan-go.svg)](https://microbadger.com/images/p4gefau1t/trojan-go) [![Commit](https://img.shields.io/github/last-commit/p4gefau1t/trojan-go)](https://img.shields.io/github/last-commit/p4gefau1t/trojan-go) [![Commit Activity](https://img.shields.io/github/commit-activity/m/p4gefau1t/trojan-go)](https://img.shields.io/github/commit-activity/m/p4gefau1t/trojan-go) +[![Go Report Card](https://goreportcard.com/badge/github.com/p4gefau1t/trojan-go)](https://goreportcard.com/report/github.com/p4gefau1t/trojan-go) 使用Go实现的完整Trojan代理,与Trojan协议以及Trojan-GFW版本的配置文件格式兼容。安全,高效,轻巧,易用。 @@ -27,7 +27,7 @@ ### 下面的说明为简单介绍,完整配置教程和配置介绍参见[Trojan-Go文档](https://p4gefau1t.github.io/trojan-go)。 -Trojan-Go支持并且兼容原版Trojan-GFW的绝大多数功能,包括但不限于: +Trojan-Go支持并且兼容Trojan-GFW的绝大多数功能,包括但不限于: - TLS/SSL隧道传输 @@ -144,7 +144,7 @@ CGO_ENABLE=0 GOOS=linux GOARCH=mips go build -tags "client" ### 易用 -配置文件格式与原版兼容,但做了大幅简化,未指定的字段会被附上一个默认值。你可以更方便地部署你的服务器和客户端。下面是一个简单的例子,完整的配置文件可以参见[这里](https://p4gefau1t.github.io/trojan-go)。 +配置文件格式与Trojan-GFW兼容,但做了大幅简化,未指定的字段会被附上一个默认值。你可以更方便地部署你的服务器和客户端。下面是一个简单的例子,完整的配置文件可以参见[这里](https://p4gefau1t.github.io/trojan-go)。 服务器配置文件 @@ -241,9 +241,9 @@ Trojan-Go支持使用TLS+Websocket承载Trojan协议,使得利用CDN进行流 完整的选项说明参见[Trojan-Go 文档](https://p4gefau1t.github.io/trojan-go)。 -服务端可以省略```hostname```, 但是服务器和客户端的```path```必须相同。服务器开启Websocket支持后可以同时支持Websocket和一般Trojan流量,未配置Websocket选项的客户端依然可以正常使用。 +可以省略```hostname```, 但是服务器和客户端的```path```必须一致。服务器开启Websocket支持后可以同时支持Websocket和一般Trojan流量,未配置Websocket选项的客户端依然可以正常使用。 -由于原版Trojan并不支持Websocket,因此,虽然开启了Websocket支持的服务端可以兼容原版Trojan客户端,但是如果要使用Websocket承载流量进行CDN中转等,请确保双方都使用Trojan-Go。 +由于Trojan-GFW版本并不支持Websocket,因此,虽然开启了Websocket支持的服务端可以兼容所有客户端,但是如果要使用Websocket承载流量,请确保双方都使用Trojan-Go。 ### 多路复用 @@ -255,7 +255,7 @@ Trojan-Go支持多路复用([smux](https://github.com/xtaci/smux))。通过使 启用多路复用并不会增加你测速得到的链路速度,但会降低延迟,提升大量并发请求时的网络体验,例如浏览含有大量图片的网页等。 -注意,这个特性和原版Trojan**不兼容**,所以出于兼容性考虑,这个特性是默认关闭的。你可以通过设置mux选项中的"enabled"字段启用它。如下 +注意,这个特性和Trojan-GFW**不兼容**,所以出于兼容性考虑,这个特性是默认关闭的。你可以通过设置mux选项中的"enabled"字段启用它。如下 ```json "mux": { @@ -297,7 +297,8 @@ Trojan-Go的客户端内建一个简单实用的路由模块用以方便实现 ], "proxy": [ "proxy_list.txt" - ] + ], + "default_policy": "proxy" } ``` @@ -357,3 +358,8 @@ CGO_ENABLE=0 GOOS=linux GOARCH=arm go build -tags "full" -o trojan-go [tcplisten](https://github.com/valyala/tcplisten) [utls](https://github.com/refraction-networking/utls) + + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/p4gefau1t/trojan-go.svg)](https://starchart.cc/p4gefau1t/trojan-go) \ No newline at end of file diff --git a/build.sh b/build.sh index 79d15013f..c60a4b33c 100755 --- a/build.sh +++ b/build.sh @@ -1 +1,3 @@ +#!/bin/bash + CGO_ENABLE=0 go build -tags "full" -ldflags="-s -w" diff --git a/common/net.go b/common/net.go index e40b6acae..7afaf2f98 100644 --- a/common/net.go +++ b/common/net.go @@ -40,18 +40,18 @@ func (a *Address) Network() string { return a.NetworkType } -func (a *Address) ResolveIP(preferV4 bool) (net.IP, error) { +func (a *Address) ResolveIP() (net.IP, error) { if a.AddressType == IPv4 || a.AddressType == IPv6 { return a.IP, nil } - network := "ip" - if preferV4 { - network = "ip4" + if a.IP != nil { + return a.IP, nil } - addr, err := net.ResolveIPAddr(network, a.DomainName) + addr, err := net.ResolveIPAddr("ip", a.DomainName) if err != nil { return nil, err } + a.IP = addr.IP return addr.IP, nil } diff --git a/protocol/simplesocks/simplesocks.go b/protocol/simplesocks/simplesocks.go index d02ca5d1a..1f719cacf 100644 --- a/protocol/simplesocks/simplesocks.go +++ b/protocol/simplesocks/simplesocks.go @@ -5,7 +5,6 @@ import ( "io" "github.com/p4gefau1t/trojan-go/common" - "github.com/p4gefau1t/trojan-go/conf" "github.com/p4gefau1t/trojan-go/log" "github.com/p4gefau1t/trojan-go/protocol" ) @@ -13,7 +12,6 @@ import ( type SimpleSocksConnSession struct { protocol.ConnSession - config *conf.GlobalConfig request *protocol.Request rwc io.ReadWriteCloser recv uint64 diff --git a/protocol/socks/inbound.go b/protocol/socks/inbound.go index 3a3563e5c..c4853c9f2 100644 --- a/protocol/socks/inbound.go +++ b/protocol/socks/inbound.go @@ -127,7 +127,7 @@ type SocksInboundPacketSession struct { func (i *SocksInboundPacketSession) parsePacket(rawPacket []byte) (*protocol.Request, []byte, error) { if len(rawPacket) <= 4 { - return nil, nil, common.NewError("too short") + return nil, nil, common.NewError("packet too short") } buf := bytes.NewBuffer(rawPacket) buf.Next(2) @@ -139,7 +139,7 @@ func (i *SocksInboundPacketSession) parsePacket(rawPacket []byte) (*protocol.Req if err != nil { return nil, nil, common.NewError("cannot parse udp request").Base(err) } - //command make no sense here + //command makes no sense here request := &protocol.Request{ Address: addr, } diff --git a/protocol/tproxy/inbound.go b/protocol/tproxy/inbound.go index 9d1ec6d0c..520f65300 100644 --- a/protocol/tproxy/inbound.go +++ b/protocol/tproxy/inbound.go @@ -157,7 +157,7 @@ func (i *NATInboundPacketSession) Close() error { } func NewInboundPacketSession(ctx context.Context, config *conf.GlobalConfig) (protocol.PacketSession, error) { - localIP, err := config.LocalAddress.ResolveIP(false) + localIP, err := config.LocalAddress.ResolveIP() if err != nil { return nil, err } diff --git a/proxy/client/client.go b/proxy/client/client.go index 16b4de28b..cbf2b2b1a 100644 --- a/proxy/client/client.go +++ b/proxy/client/client.go @@ -37,7 +37,7 @@ type Client struct { associated *common.Notifier router router.Router tcpListener net.Listener - udpListener *net.UDPConn + udpListener net.PacketConn auth stat.Authenticator appMan *AppManager } @@ -55,7 +55,7 @@ func (c *Client) handleSocksConn(conn io.ReadWriteCloser) { if req.Command == protocol.Associate { //setting up the bind address to respond //listenUDP() will handle the incoming udp packets - localIP, err := c.config.LocalAddress.ResolveIP(false) + localIP, err := c.config.LocalAddress.ResolveIP() if err != nil { log.Error(common.NewError("invalid local address").Base(err)) return @@ -233,21 +233,13 @@ func (c *Client) handleHTTPConn(conn io.ReadWriteCloser) { } func (c *Client) listenUDP(errChan chan error) { - localIP, err := c.config.LocalAddress.ResolveIP(false) - if err != nil { - errChan <- common.NewError("invalid local address").Base(err) - return - } - listener, err := net.ListenUDP("udp", &net.UDPAddr{ - IP: localIP, - Port: c.config.LocalAddress.Port, - }) + listener, err := net.ListenPacket("udp", c.config.LocalAddress.String()) if err != nil { errChan <- common.NewError("failed to listen udp").Base(err) return } c.udpListener = listener - inboundPacket, err := socks.NewInboundPacketSession(c.ctx, listener) + inboundPacket, err := socks.NewInboundPacketSession(c.ctx, listener.(*net.UDPConn)) common.Must(err) for { select { diff --git a/proxy/client/forward.go b/proxy/client/forward.go index 0295e90f3..619666fb6 100644 --- a/proxy/client/forward.go +++ b/proxy/client/forward.go @@ -16,7 +16,7 @@ import ( ) type dispatchInfo struct { - addr *net.UDPAddr + addr net.Addr payload []byte } @@ -30,13 +30,13 @@ type Forward struct { clientPackets chan *dispatchInfo outboundPacketTableLock sync.Mutex outboundPacketTable map[string]protocol.PacketSession - udpListener *net.UDPConn + udpListener net.PacketConn tcpListener net.Listener auth stat.Authenticator appMan *AppManager } -func (f *Forward) dispatchServerPacket(addr *net.UDPAddr) { +func (f *Forward) dispatchServerPacket(addr net.Addr) { for { f.outboundPacketTableLock.Lock() //use src addr as the key @@ -110,11 +110,7 @@ func (f *Forward) dispatchClientPacket() { } func (f *Forward) listenUDP(errChan chan error) { - localIP, err := f.config.LocalAddress.ResolveIP(false) - listener, err := net.ListenUDP("udp", &net.UDPAddr{ - IP: localIP, - Port: f.config.LocalAddress.Port, - }) + listener, err := net.ListenPacket("udp", f.config.LocalAddress.String()) if err != nil { errChan <- common.NewError("failed to listen udp") return @@ -123,7 +119,7 @@ func (f *Forward) listenUDP(errChan chan error) { go f.dispatchClientPacket() for { buf := make([]byte, protocol.MaxUDPPacketSize) - n, addr, err := listener.ReadFromUDP(buf) + n, addr, err := listener.ReadFrom(buf) log.Info("packet from", addr, "tunneling to", f.config.TargetAddress) if err != nil { errChan <- err diff --git a/proxy/client/nat.go b/proxy/client/nat.go index d8fe3c209..1ba5851fe 100644 --- a/proxy/client/nat.go +++ b/proxy/client/nat.go @@ -77,15 +77,7 @@ func (n *NAT) listenUDP(errChan chan error) { } func (n *NAT) listenTCP(errChan chan error) { - localIP, err := n.config.LocalAddress.ResolveIP(false) - if err != nil { - errChan <- err - return - } - listener, err := net.ListenTCP("tcp", &net.TCPAddr{ - IP: localIP, - Port: int(n.config.LocalAddress.Port), - }) + listener, err := net.Listen("tcp", n.config.LocalAddress.String()) if err != nil { errChan <- err return