mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-30 05:56:54 -05:00
Refine code according to golangci-lint results
This commit is contained in:
parent
ff6bb51732
commit
784775f689
@ -22,9 +22,9 @@ func (l *OutboundListener) add(conn net.Conn) {
|
||||
select {
|
||||
case l.buffer <- conn:
|
||||
case <-l.done.Wait():
|
||||
conn.Close() // nolint: errcheck
|
||||
conn.Close()
|
||||
default:
|
||||
conn.Close() // nolint: errcheck
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ L:
|
||||
for {
|
||||
select {
|
||||
case c := <-l.buffer:
|
||||
c.Close() // nolint: errcheck
|
||||
c.Close()
|
||||
default:
|
||||
break L
|
||||
}
|
||||
|
@ -89,7 +89,6 @@ func Test_parseResponse(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_buildReqMsgs(t *testing.T) {
|
||||
|
||||
stubID := func() uint16 {
|
||||
return uint16(rand.Uint32())
|
||||
}
|
||||
|
@ -43,7 +43,6 @@ type DoHNameServer struct {
|
||||
|
||||
// NewDoHNameServer creates DOH client object for remote resolving
|
||||
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.IP) (*DoHNameServer, error) {
|
||||
|
||||
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog()
|
||||
s := baseDOHNameServer(url, "DOH", clientIP)
|
||||
|
||||
@ -112,7 +111,6 @@ func NewDoHLocalNameServer(url *url.URL, clientIP net.IP) *DoHNameServer {
|
||||
}
|
||||
|
||||
func baseDOHNameServer(url *url.URL, prefix string, clientIP net.IP) *DoHNameServer {
|
||||
|
||||
s := &DoHNameServer{
|
||||
ips: make(map[string]record),
|
||||
clientIP: clientIP,
|
||||
|
@ -66,7 +66,8 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
||||
}
|
||||
id := g.Add(matcher)
|
||||
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
||||
if len(mapping.Ip) > 0 {
|
||||
switch {
|
||||
case len(mapping.Ip) > 0:
|
||||
for _, ip := range mapping.Ip {
|
||||
addr := net.IPAddress(ip)
|
||||
if addr == nil {
|
||||
@ -74,9 +75,11 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
||||
}
|
||||
ips = append(ips, addr)
|
||||
}
|
||||
} else if len(mapping.ProxiedDomain) > 0 {
|
||||
|
||||
case len(mapping.ProxiedDomain) > 0:
|
||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
||||
} else {
|
||||
|
||||
default:
|
||||
return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,11 @@ type Client interface {
|
||||
QueryIP(ctx context.Context, domain string, option IPOption) ([]net.IP, error)
|
||||
}
|
||||
|
||||
type localNameServer struct {
|
||||
type LocalNameServer struct {
|
||||
client *localdns.Client
|
||||
}
|
||||
|
||||
func (s *localNameServer) QueryIP(ctx context.Context, domain string, option IPOption) ([]net.IP, error) {
|
||||
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, option IPOption) ([]net.IP, error) {
|
||||
if option.IPv4Enable && option.IPv6Enable {
|
||||
return s.client.LookupIP(domain)
|
||||
}
|
||||
@ -44,13 +44,13 @@ func (s *localNameServer) QueryIP(ctx context.Context, domain string, option IPO
|
||||
return nil, newError("neither IPv4 nor IPv6 is enabled")
|
||||
}
|
||||
|
||||
func (s *localNameServer) Name() string {
|
||||
func (s *LocalNameServer) Name() string {
|
||||
return "localhost"
|
||||
}
|
||||
|
||||
func NewLocalNameServer() *localNameServer {
|
||||
func NewLocalNameServer() *LocalNameServer {
|
||||
newError("DNS: created localhost client").AtInfo().WriteToLog()
|
||||
return &localNameServer{
|
||||
return &LocalNameServer{
|
||||
client: localdns.New(),
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,9 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
||||
addNameServer := func(ns *NameServer) int {
|
||||
endpoint := ns.Address
|
||||
address := endpoint.Address.AsAddress()
|
||||
if address.Family().IsDomain() && address.Domain() == "localhost" {
|
||||
|
||||
switch {
|
||||
case address.Family().IsDomain() && address.Domain() == "localhost":
|
||||
server.clients = append(server.clients, NewLocalNameServer())
|
||||
// Priotize local domains with specific TLDs or without any dot to local DNS
|
||||
// References:
|
||||
@ -115,7 +117,8 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
||||
{Type: DomainMatchingType_Subdomain, Domain: "test"},
|
||||
}
|
||||
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
|
||||
} else if address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https+local://") {
|
||||
|
||||
case address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https+local://"):
|
||||
// URI schemed string treated as domain
|
||||
// DOH Local mode
|
||||
u, err := url.Parse(address.Domain())
|
||||
@ -123,7 +126,8 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
||||
log.Fatalln(newError("DNS config error").Base(err))
|
||||
}
|
||||
server.clients = append(server.clients, NewDoHLocalNameServer(u, server.clientIP))
|
||||
} else if address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https://") {
|
||||
|
||||
case address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https://"):
|
||||
// DOH Remote mode
|
||||
u, err := url.Parse(address.Domain())
|
||||
if err != nil {
|
||||
@ -140,7 +144,8 @@ func New(ctx context.Context, config *Config) (*Server, error) {
|
||||
}
|
||||
server.clients[idx] = c
|
||||
}))
|
||||
} else {
|
||||
|
||||
default:
|
||||
// UDP classic DNS mode
|
||||
dest := endpoint.AsDestination()
|
||||
if dest.Network == net.Network_Unknown {
|
||||
|
@ -42,7 +42,8 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
}
|
||||
|
||||
for _, q := range r.Question {
|
||||
if q.Name == "google.com." && q.Qtype == dns.TypeA {
|
||||
switch {
|
||||
case q.Name == "google.com." && q.Qtype == dns.TypeA:
|
||||
if clientIP == nil {
|
||||
rr, _ := dns.NewRR("google.com. IN A 8.8.8.8")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
@ -50,44 +51,57 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
rr, _ := dns.NewRR("google.com. IN A 8.8.4.4")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
}
|
||||
} else if q.Name == "api.google.com." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "api.google.com." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("api.google.com. IN A 8.8.7.7")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "v2.api.google.com." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "v2.api.google.com." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("v2.api.google.com. IN A 8.8.7.8")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "facebook.com." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "facebook.com." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA:
|
||||
rr, err := dns.NewRR("ipv6.google.com. IN A 8.8.8.7")
|
||||
common.Must(err)
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA {
|
||||
|
||||
case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA:
|
||||
rr, err := dns.NewRR("ipv6.google.com. IN AAAA 2001:4860:4860::8888")
|
||||
common.Must(err)
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA {
|
||||
|
||||
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
|
||||
ans.MsgHdr.Rcode = dns.RcodeNameError
|
||||
} else if q.Name == "hostname." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "hostname." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "hostname.local." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "hostname.local." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("hostname.local. IN A 127.0.0.1")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "hostname.localdomain." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "hostname.localdomain." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("hostname.localdomain. IN A 127.0.0.1")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "localhost." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "localhost." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("localhost. IN A 127.0.0.2")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "localhost-a." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "localhost-a." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("localhost-a. IN A 127.0.0.3")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "localhost-b." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "localhost-b." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("localhost-b. IN A 127.0.0.4")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "Mijia\\ Cloud." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "Mijia\\ Cloud." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("Mijia\\ Cloud. IN A 127.0.0.1")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ type ClassicNameServer struct {
|
||||
}
|
||||
|
||||
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, clientIP net.IP) *ClassicNameServer {
|
||||
|
||||
// default to 53 if unspecific
|
||||
if address.Port == 0 {
|
||||
address.Port = net.Port(53)
|
||||
@ -105,7 +104,6 @@ func (s *ClassicNameServer) Cleanup() error {
|
||||
}
|
||||
|
||||
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
||||
|
||||
ipRec, err := parseResponse(packet.Payload.Bytes())
|
||||
if err != nil {
|
||||
newError(s.name, " fail to parse responded DNS udp").AtError().WriteToLog()
|
||||
@ -240,7 +238,6 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option IPOption) ([]
|
||||
}
|
||||
|
||||
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option IPOption) ([]net.IP, error) {
|
||||
|
||||
fqdn := Fqdn(domain)
|
||||
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
|
@ -127,10 +127,10 @@ func (g *Instance) Close() error {
|
||||
|
||||
g.active = false
|
||||
|
||||
common.Close(g.accessLogger) // nolint: errcheck
|
||||
common.Close(g.accessLogger)
|
||||
g.accessLogger = nil
|
||||
|
||||
common.Close(g.errorLogger) // nolint: errcheck
|
||||
common.Close(g.errorLogger)
|
||||
g.errorLogger = nil
|
||||
|
||||
return nil
|
||||
|
@ -280,7 +280,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
conn, existing := w.getConnection(id)
|
||||
|
||||
// payload will be discarded in pipe is full.
|
||||
conn.writer.WriteMultiBuffer(buf.MultiBuffer{b}) // nolint: errcheck
|
||||
conn.writer.WriteMultiBuffer(buf.MultiBuffer{b})
|
||||
|
||||
if !existing {
|
||||
common.Must(w.checker.Start())
|
||||
@ -303,7 +303,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
||||
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
conn.Close() // nolint: errcheck
|
||||
conn.Close()
|
||||
w.removeConn(id)
|
||||
}()
|
||||
}
|
||||
@ -332,9 +332,9 @@ func (w *udpWorker) clean() error {
|
||||
}
|
||||
|
||||
for addr, conn := range w.activeConn {
|
||||
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 8 { //TODO Timeout too small
|
||||
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 8 { // TODO Timeout too small
|
||||
delete(w.activeConn, addr)
|
||||
conn.Close() // nolint: errcheck
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ func (s *routingServer) TestRoute(ctx context.Context, request *TestRouteRequest
|
||||
return nil, err
|
||||
}
|
||||
if request.PublishResult && s.routingStats != nil {
|
||||
ctx, _ := context.WithTimeout(context.Background(), 4*time.Second) // nolint: govet
|
||||
ctx, _ := context.WithTimeout(context.Background(), 4*time.Second)
|
||||
s.routingStats.Publish(ctx, route)
|
||||
}
|
||||
return AsProtobufMessage(request.FieldSelectors)(route), nil
|
||||
@ -54,7 +54,7 @@ func (s *routingServer) SubscribeRoutingStats(request *SubscribeRoutingStatsRequ
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stats.UnsubscribeClosableChannel(s.routingStats, subscriber) // nolint: errcheck
|
||||
defer stats.UnsubscribeClosableChannel(s.routingStats, subscriber)
|
||||
for {
|
||||
select {
|
||||
case value, ok := <-subscriber:
|
||||
|
@ -34,12 +34,12 @@ func TestSimpleRouter(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDns := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
mockOhm := mocks.NewOutboundManager(mockCtl)
|
||||
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDns, &mockOutboundManager{
|
||||
common.Must(r.Init(config, mockDNS, &mockOutboundManager{
|
||||
Manager: mockOhm,
|
||||
HandlerSelector: mockHs,
|
||||
}))
|
||||
@ -73,14 +73,14 @@ func TestSimpleBalancer(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDns := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
mockOhm := mocks.NewOutboundManager(mockCtl)
|
||||
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
||||
|
||||
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"})
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDns, &mockOutboundManager{
|
||||
common.Must(r.Init(config, mockDNS, &mockOutboundManager{
|
||||
Manager: mockOhm,
|
||||
HandlerSelector: mockHs,
|
||||
}))
|
||||
@ -114,11 +114,11 @@ func TestIPOnDemand(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDns := mocks.NewDNSClient(mockCtl)
|
||||
mockDns.EXPECT().LookupIP(gomock.Eq("v2ray.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS.EXPECT().LookupIP(gomock.Eq("v2ray.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDns, nil))
|
||||
common.Must(r.Init(config, mockDNS, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
@ -149,11 +149,11 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDns := mocks.NewDNSClient(mockCtl)
|
||||
mockDns.EXPECT().LookupIP(gomock.Eq("v2ray.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS.EXPECT().LookupIP(gomock.Eq("v2ray.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDns, nil))
|
||||
common.Must(r.Init(config, mockDNS, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
@ -184,10 +184,10 @@ func TestIPIfNonMatchIP(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
defer mockCtl.Finish()
|
||||
|
||||
mockDns := mocks.NewDNSClient(mockCtl)
|
||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||
|
||||
r := new(Router)
|
||||
common.Must(r.Init(config, mockDns, nil))
|
||||
common.Must(r.Init(config, mockDNS, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
|
@ -388,7 +388,7 @@ func TestStatsChannelConcurrency(t *testing.T) {
|
||||
if ok {
|
||||
errCh <- fmt.Sprint("unexpected receiving: ", v)
|
||||
} else {
|
||||
errCh <- fmt.Sprint("unexpected closing of channel")
|
||||
errCh <- "unexpected closing of channel"
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
package antireplay
|
||||
|
||||
import (
|
||||
cuckoo "github.com/seiflotfy/cuckoofilter"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
cuckoo "github.com/seiflotfy/cuckoofilter"
|
||||
)
|
||||
|
||||
func NewAntiReplayWindow(AntiReplayTime int64) *AntiReplayWindow {
|
||||
func NewAntiReplayWindow(antiReplayTime int64) *AntiReplayWindow {
|
||||
arw := &AntiReplayWindow{}
|
||||
arw.AntiReplayTime = AntiReplayTime
|
||||
arw.AntiReplayTime = antiReplayTime
|
||||
return arw
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,11 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
. "v2ray.com/core/common/buf"
|
||||
)
|
||||
@ -110,7 +109,6 @@ func TestMultiBufferReadAllToByte(t *testing.T) {
|
||||
if l := len(b); l != 8*1024 {
|
||||
t.Error("unexpceted length from ReadAllToBytes", l)
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
const dat = "data/test_MultiBufferReadAllToByte.dat"
|
||||
|
@ -88,7 +88,6 @@ func TestReadBuffer(t *testing.T) {
|
||||
}
|
||||
buf.Release()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestReadAtMost(t *testing.T) {
|
||||
|
@ -23,11 +23,11 @@ func TestReadvReader(t *testing.T) {
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close() // nolint: errcheck
|
||||
defer tcpServer.Close()
|
||||
|
||||
conn, err := net.Dial("tcp", dest.NetAddr())
|
||||
common.Must(err)
|
||||
defer conn.Close() // nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
const size = 8192
|
||||
data := make([]byte, 8192)
|
||||
|
@ -65,7 +65,7 @@ func Free(b []byte) {
|
||||
b = b[0:cap(b)]
|
||||
for i := numPools - 1; i >= 0; i-- {
|
||||
if size >= poolSize[i] {
|
||||
pool[i].Put(b) // nolint: megacheck
|
||||
pool[i].Put(b)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -32,15 +32,15 @@ func RollUint64() uint64 {
|
||||
return rand.Uint64()
|
||||
}
|
||||
|
||||
func NewDeterministicDice(seed int64) *deterministicDice {
|
||||
return &deterministicDice{rand.New(rand.NewSource(seed))}
|
||||
func NewDeterministicDice(seed int64) *DeterministicDice {
|
||||
return &DeterministicDice{rand.New(rand.NewSource(seed))}
|
||||
}
|
||||
|
||||
type deterministicDice struct {
|
||||
type DeterministicDice struct {
|
||||
*rand.Rand
|
||||
}
|
||||
|
||||
func (dd *deterministicDice) Roll(n int) int {
|
||||
func (dd *DeterministicDice) Roll(n int) int {
|
||||
if n == 1 {
|
||||
return 0
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ func (l *generalLogger) run() {
|
||||
if logger == nil {
|
||||
return
|
||||
}
|
||||
defer logger.Close() // nolint: errcheck
|
||||
defer logger.Close()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-l.done.Wait():
|
||||
return
|
||||
case msg := <-l.buffer:
|
||||
logger.Write(msg.String() + platform.LineSeparator()) // nolint: errcheck
|
||||
logger.Write(msg.String() + platform.LineSeparator())
|
||||
dataWritten = true
|
||||
case <-ticker.C:
|
||||
if !dataWritten {
|
||||
|
@ -29,7 +29,7 @@ func TestFileLogger(t *testing.T) {
|
||||
|
||||
f, err = os.Open(path)
|
||||
common.Must(err)
|
||||
defer f.Close() // nolint: errcheck
|
||||
defer f.Close()
|
||||
|
||||
b, err := buf.ReadAllToBytes(f)
|
||||
common.Must(err)
|
||||
|
@ -214,8 +214,8 @@ func (m *ClientWorker) monitor() {
|
||||
select {
|
||||
case <-m.done.Wait():
|
||||
m.sessionManager.Close()
|
||||
common.Close(m.link.Writer) // nolint: errcheck
|
||||
common.Interrupt(m.link.Reader) // nolint: errcheck
|
||||
common.Close(m.link.Writer)
|
||||
common.Interrupt(m.link.Reader)
|
||||
return
|
||||
case <-timer.C:
|
||||
size := m.sessionManager.Size()
|
||||
@ -247,8 +247,8 @@ func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
|
||||
}
|
||||
s.transferType = transferType
|
||||
writer := NewWriter(s.ID, dest, output, transferType)
|
||||
defer s.Close() // nolint: errcheck
|
||||
defer writer.Close() // nolint: errcheck
|
||||
defer s.Close()
|
||||
defer writer.Close()
|
||||
|
||||
newError("dispatching request to ", dest).WriteToLog(session.ExportIDToError(ctx))
|
||||
if err := writeFirstPayload(s.input, writer); err != nil {
|
||||
|
@ -232,7 +232,7 @@ func (w *ServerWorker) run(ctx context.Context) {
|
||||
input := w.link.Reader
|
||||
reader := &buf.BufferedReader{Reader: input}
|
||||
|
||||
defer w.sessionManager.Close() // nolint: errcheck
|
||||
defer w.sessionManager.Close()
|
||||
|
||||
for {
|
||||
select {
|
||||
|
@ -126,8 +126,8 @@ func (m *SessionManager) Close() error {
|
||||
m.closed = true
|
||||
|
||||
for _, s := range m.sessions {
|
||||
common.Close(s.input) // nolint: errcheck
|
||||
common.Close(s.output) // nolint: errcheck
|
||||
common.Close(s.input)
|
||||
common.Close(s.output)
|
||||
}
|
||||
|
||||
m.sessions = nil
|
||||
@ -145,8 +145,8 @@ type Session struct {
|
||||
|
||||
// Close closes all resources associated with this session.
|
||||
func (s *Session) Close() error {
|
||||
common.Close(s.output) // nolint: errcheck
|
||||
common.Close(s.input) // nolint: errcheck
|
||||
common.Close(s.output)
|
||||
common.Close(s.input)
|
||||
s.parent.Remove(s.ID)
|
||||
return nil
|
||||
}
|
||||
|
@ -121,6 +121,6 @@ func (w *Writer) Close() error {
|
||||
frame := buf.New()
|
||||
common.Must(meta.WriteTo(frame))
|
||||
|
||||
w.writer.WriteMultiBuffer(buf.MultiBuffer{frame}) // nolint: errcheck
|
||||
w.writer.WriteMultiBuffer(buf.MultiBuffer{frame})
|
||||
return nil
|
||||
}
|
||||
|
@ -90,10 +90,8 @@ func TestDestinationParse(t *testing.T) {
|
||||
if d != testcase.Output {
|
||||
t.Error("for test case: ", testcase.Input, " expected output: ", testcase.Output.String(), " but got ", d.String())
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Error("for test case: ", testcase.Input, " expected error, but got nil")
|
||||
}
|
||||
} else if err == nil {
|
||||
t.Error("for test case: ", testcase.Input, " expected error, but got nil")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (f EnvFlag) GetValueAsInt(defaultValue int) int {
|
||||
}
|
||||
|
||||
func NormalizeEnvName(name string) string {
|
||||
return strings.Replace(strings.ToUpper(strings.TrimSpace(name)), ".", "_", -1)
|
||||
return strings.ReplaceAll(strings.ToUpper(strings.TrimSpace(name)), ".", "_")
|
||||
}
|
||||
|
||||
func getExecutableDir() string {
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/task"
|
||||
)
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
errorTestOnly = errors.New("This is a fake error.")
|
||||
errorTestOnly = errors.New("this is a fake error")
|
||||
)
|
||||
|
||||
func TestNoRetry(t *testing.T) {
|
||||
|
@ -45,7 +45,7 @@ func (t *ActivityTimer) finish() {
|
||||
t.onTimeout = nil
|
||||
}
|
||||
if t.checkTask != nil {
|
||||
t.checkTask.Close() // nolint: errcheck
|
||||
t.checkTask.Close()
|
||||
t.checkTask = nil
|
||||
}
|
||||
}
|
||||
@ -64,7 +64,7 @@ func (t *ActivityTimer) SetTimeout(timeout time.Duration) {
|
||||
t.Lock()
|
||||
|
||||
if t.checkTask != nil {
|
||||
t.checkTask.Close() // nolint: errcheck
|
||||
t.checkTask.Close()
|
||||
}
|
||||
t.checkTask = checkTask
|
||||
t.Unlock()
|
||||
|
@ -44,7 +44,7 @@ func (t *Periodic) checkedExecute() error {
|
||||
}
|
||||
|
||||
t.timer = time.AfterFunc(t.Interval, func() {
|
||||
t.checkedExecute() // nolint: errcheck
|
||||
t.checkedExecute()
|
||||
})
|
||||
|
||||
return nil
|
||||
|
@ -117,8 +117,8 @@ func defaultBufferPolicy() Buffer {
|
||||
func SessionDefault() Session {
|
||||
return Session{
|
||||
Timeouts: Timeout{
|
||||
//Align Handshake timeout with nginx client_header_timeout
|
||||
//So that this value will not indicate server identity
|
||||
// Align Handshake timeout with nginx client_header_timeout
|
||||
// So that this value will not indicate server identity
|
||||
Handshake: time.Second * 60,
|
||||
ConnectionIdle: time.Second * 300,
|
||||
UplinkOnly: time.Second * 1,
|
||||
|
@ -10,14 +10,14 @@ import (
|
||||
"v2ray.com/core/common/serial"
|
||||
)
|
||||
|
||||
type ApiConfig struct {
|
||||
type APIConfig struct {
|
||||
Tag string `json:"tag"`
|
||||
Services []string `json:"services"`
|
||||
}
|
||||
|
||||
func (c *ApiConfig) Build() (*commander.Config, error) {
|
||||
func (c *APIConfig) Build() (*commander.Config, error) {
|
||||
if c.Tag == "" {
|
||||
return nil, newError("Api tag can't be empty.")
|
||||
return nil, newError("API tag can't be empty.")
|
||||
}
|
||||
|
||||
services := make([]*serial.TypedMessage, 0, 16)
|
||||
|
@ -15,9 +15,9 @@ func (*NoneResponse) Build() (proto.Message, error) {
|
||||
return new(blackhole.NoneResponse), nil
|
||||
}
|
||||
|
||||
type HttpResponse struct{}
|
||||
type HTTPResponse struct{}
|
||||
|
||||
func (*HttpResponse) Build() (proto.Message, error) {
|
||||
func (*HTTPResponse) Build() (proto.Message, error) {
|
||||
return new(blackhole.HTTPResponse), nil
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ var (
|
||||
configLoader = NewJSONConfigLoader(
|
||||
ConfigCreatorCache{
|
||||
"none": func() interface{} { return new(NoneResponse) },
|
||||
"http": func() interface{} { return new(HttpResponse) },
|
||||
"http": func() interface{} { return new(HTTPResponse) },
|
||||
},
|
||||
"type",
|
||||
"")
|
||||
|
@ -221,7 +221,7 @@ func (list *PortList) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
}
|
||||
if number != 0 {
|
||||
list.Range = append(list.Range, PortRange{From: uint32(number), To: uint32(number)})
|
||||
list.Range = append(list.Range, PortRange{From: number, To: number})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,31 +2,31 @@ package conf_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"v2ray.com/core/common/protocol"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/protocol"
|
||||
. "v2ray.com/core/infra/conf"
|
||||
)
|
||||
|
||||
func TestStringListUnmarshalError(t *testing.T) {
|
||||
rawJson := `1234`
|
||||
rawJSON := `1234`
|
||||
list := new(StringList)
|
||||
err := json.Unmarshal([]byte(rawJson), list)
|
||||
err := json.Unmarshal([]byte(rawJSON), list)
|
||||
if err == nil {
|
||||
t.Error("expected error, but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringListLen(t *testing.T) {
|
||||
rawJson := `"a, b, c, d"`
|
||||
rawJSON := `"a, b, c, d"`
|
||||
var list StringList
|
||||
err := json.Unmarshal([]byte(rawJson), &list)
|
||||
err := json.Unmarshal([]byte(rawJSON), &list)
|
||||
common.Must(err)
|
||||
if r := cmp.Diff([]string(list), []string{"a", " b", " c", " d"}); r != "" {
|
||||
t.Error(r)
|
||||
@ -34,9 +34,9 @@ func TestStringListLen(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIPParsing(t *testing.T) {
|
||||
rawJson := "\"8.8.8.8\""
|
||||
rawJSON := "\"8.8.8.8\""
|
||||
var address Address
|
||||
err := json.Unmarshal([]byte(rawJson), &address)
|
||||
err := json.Unmarshal([]byte(rawJSON), &address)
|
||||
common.Must(err)
|
||||
if r := cmp.Diff(address.IP(), net.IP{8, 8, 8, 8}); r != "" {
|
||||
t.Error(r)
|
||||
@ -44,9 +44,9 @@ func TestIPParsing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDomainParsing(t *testing.T) {
|
||||
rawJson := "\"v2ray.com\""
|
||||
rawJSON := "\"v2ray.com\""
|
||||
var address Address
|
||||
common.Must(json.Unmarshal([]byte(rawJson), &address))
|
||||
common.Must(json.Unmarshal([]byte(rawJSON), &address))
|
||||
if address.Domain() != "v2ray.com" {
|
||||
t.Error("domain: ", address.Domain())
|
||||
}
|
||||
@ -54,17 +54,17 @@ func TestDomainParsing(t *testing.T) {
|
||||
|
||||
func TestURLParsing(t *testing.T) {
|
||||
{
|
||||
rawJson := "\"https://dns.google/dns-query\""
|
||||
rawJSON := "\"https://dns.google/dns-query\""
|
||||
var address Address
|
||||
common.Must(json.Unmarshal([]byte(rawJson), &address))
|
||||
common.Must(json.Unmarshal([]byte(rawJSON), &address))
|
||||
if address.Domain() != "https://dns.google/dns-query" {
|
||||
t.Error("URL: ", address.Domain())
|
||||
}
|
||||
}
|
||||
{
|
||||
rawJson := "\"https+local://dns.google/dns-query\""
|
||||
rawJSON := "\"https+local://dns.google/dns-query\""
|
||||
var address Address
|
||||
common.Must(json.Unmarshal([]byte(rawJson), &address))
|
||||
common.Must(json.Unmarshal([]byte(rawJSON), &address))
|
||||
if address.Domain() != "https+local://dns.google/dns-query" {
|
||||
t.Error("URL: ", address.Domain())
|
||||
}
|
||||
@ -72,9 +72,9 @@ func TestURLParsing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestInvalidAddressJson(t *testing.T) {
|
||||
rawJson := "1234"
|
||||
rawJSON := "1234"
|
||||
var address Address
|
||||
err := json.Unmarshal([]byte(rawJson), &address)
|
||||
err := json.Unmarshal([]byte(rawJSON), &address)
|
||||
if err == nil {
|
||||
t.Error("nil error")
|
||||
}
|
||||
|
@ -106,8 +106,8 @@ var typeMap = map[router.Domain_Type]dns.DomainMatchingType{
|
||||
router.Domain_Regex: dns.DomainMatchingType_Regex,
|
||||
}
|
||||
|
||||
// DnsConfig is a JSON serializable object for dns.Config.
|
||||
type DnsConfig struct {
|
||||
// DNSConfig is a JSON serializable object for dns.Config.
|
||||
type DNSConfig struct {
|
||||
Servers []*NameServerConfig `json:"servers"`
|
||||
Hosts map[string]*Address `json:"hosts"`
|
||||
ClientIP *Address `json:"clientIp"`
|
||||
@ -127,7 +127,7 @@ func getHostMapping(addr *Address) *dns.Config_HostMapping {
|
||||
}
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *DnsConfig) Build() (*dns.Config, error) {
|
||||
func (c *DNSConfig) Build() (*dns.Config, error) {
|
||||
config := &dns.Config{
|
||||
Tag: c.Tag,
|
||||
}
|
||||
@ -153,16 +153,18 @@ func (c *DnsConfig) Build() (*dns.Config, error) {
|
||||
domains = append(domains, domain)
|
||||
}
|
||||
sort.Strings(domains)
|
||||
|
||||
for _, domain := range domains {
|
||||
addr := c.Hosts[domain]
|
||||
var mappings []*dns.Config_HostMapping
|
||||
if strings.HasPrefix(domain, "domain:") {
|
||||
switch {
|
||||
case strings.HasPrefix(domain, "domain:"):
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = dns.DomainMatchingType_Subdomain
|
||||
mapping.Domain = domain[7:]
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
} else if strings.HasPrefix(domain, "geosite:") {
|
||||
|
||||
case strings.HasPrefix(domain, "geosite:"):
|
||||
domains, err := loadGeositeWithAttr("geosite.dat", strings.ToUpper(domain[8:]))
|
||||
if err != nil {
|
||||
return nil, newError("invalid geosite settings: ", domain).Base(err)
|
||||
@ -171,28 +173,28 @@ func (c *DnsConfig) Build() (*dns.Config, error) {
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = typeMap[d.Type]
|
||||
mapping.Domain = d.Value
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
}
|
||||
} else if strings.HasPrefix(domain, "regexp:") {
|
||||
|
||||
case strings.HasPrefix(domain, "regexp:"):
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = dns.DomainMatchingType_Regex
|
||||
mapping.Domain = domain[7:]
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
} else if strings.HasPrefix(domain, "keyword:") {
|
||||
|
||||
case strings.HasPrefix(domain, "keyword:"):
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = dns.DomainMatchingType_Keyword
|
||||
mapping.Domain = domain[8:]
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
} else if strings.HasPrefix(domain, "full:") {
|
||||
|
||||
case strings.HasPrefix(domain, "full:"):
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = dns.DomainMatchingType_Full
|
||||
mapping.Domain = domain[5:]
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
} else if strings.HasPrefix(domain, "dotless:") {
|
||||
|
||||
case strings.HasPrefix(domain, "dotless:"):
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = dns.DomainMatchingType_Regex
|
||||
switch substr := domain[8:]; {
|
||||
@ -203,9 +205,9 @@ func (c *DnsConfig) Build() (*dns.Config, error) {
|
||||
default:
|
||||
return nil, newError("substr in dotless rule should not contain a dot: ", substr)
|
||||
}
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
} else if strings.HasPrefix(domain, "ext:") {
|
||||
|
||||
case strings.HasPrefix(domain, "ext:"):
|
||||
kv := strings.Split(domain[4:], ":")
|
||||
if len(kv) != 2 {
|
||||
return nil, newError("invalid external resource: ", domain)
|
||||
@ -220,14 +222,13 @@ func (c *DnsConfig) Build() (*dns.Config, error) {
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = typeMap[d.Type]
|
||||
mapping.Domain = d.Value
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
}
|
||||
} else {
|
||||
|
||||
default:
|
||||
mapping := getHostMapping(addr)
|
||||
mapping.Type = dns.DomainMatchingType_Full
|
||||
mapping.Domain = domain
|
||||
|
||||
mappings = append(mappings, mapping)
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,13 @@ import (
|
||||
"v2ray.com/core/proxy/dns"
|
||||
)
|
||||
|
||||
type DnsOutboundConfig struct {
|
||||
type DNSOutboundConfig struct {
|
||||
Network Network `json:"network"`
|
||||
Address *Address `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
}
|
||||
|
||||
func (c *DnsOutboundConfig) Build() (proto.Message, error) {
|
||||
func (c *DNSOutboundConfig) Build() (proto.Message, error) {
|
||||
config := &dns.Config{
|
||||
Server: &net.Endpoint{
|
||||
Network: c.Network.Build(),
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
func TestDnsProxyConfig(t *testing.T) {
|
||||
creator := func() Buildable {
|
||||
return new(DnsOutboundConfig)
|
||||
return new(DNSOutboundConfig)
|
||||
}
|
||||
|
||||
runMultiTestCase(t, []TestCase{
|
||||
|
@ -45,7 +45,7 @@ func init() {
|
||||
common.Must(err)
|
||||
common.Must2(geositeFile.Write(listBytes))
|
||||
}
|
||||
func TestDnsConfigParsing(t *testing.T) {
|
||||
func TestDNSConfigParsing(t *testing.T) {
|
||||
geositePath := platform.GetAssetLocation("geosite.dat")
|
||||
defer func() {
|
||||
os.Remove(geositePath)
|
||||
@ -54,7 +54,7 @@ func TestDnsConfigParsing(t *testing.T) {
|
||||
|
||||
parserCreator := func() func(string) (proto.Message, error) {
|
||||
return func(s string) (proto.Message, error) {
|
||||
config := new(DnsConfig)
|
||||
config := new(DNSConfig)
|
||||
if err := json.Unmarshal([]byte(s), config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -9,26 +9,26 @@ import (
|
||||
"v2ray.com/core/proxy/http"
|
||||
)
|
||||
|
||||
type HttpAccount struct {
|
||||
type HTTPAccount struct {
|
||||
Username string `json:"user"`
|
||||
Password string `json:"pass"`
|
||||
}
|
||||
|
||||
func (v *HttpAccount) Build() *http.Account {
|
||||
func (v *HTTPAccount) Build() *http.Account {
|
||||
return &http.Account{
|
||||
Username: v.Username,
|
||||
Password: v.Password,
|
||||
}
|
||||
}
|
||||
|
||||
type HttpServerConfig struct {
|
||||
type HTTPServerConfig struct {
|
||||
Timeout uint32 `json:"timeout"`
|
||||
Accounts []*HttpAccount `json:"accounts"`
|
||||
Accounts []*HTTPAccount `json:"accounts"`
|
||||
Transparent bool `json:"allowTransparent"`
|
||||
UserLevel uint32 `json:"userLevel"`
|
||||
}
|
||||
|
||||
func (c *HttpServerConfig) Build() (proto.Message, error) {
|
||||
func (c *HTTPServerConfig) Build() (proto.Message, error) {
|
||||
config := &http.ServerConfig{
|
||||
Timeout: c.Timeout,
|
||||
AllowTransparent: c.Transparent,
|
||||
@ -45,16 +45,16 @@ func (c *HttpServerConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type HttpRemoteConfig struct {
|
||||
type HTTPRemoteConfig struct {
|
||||
Address *Address `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
Users []json.RawMessage `json:"users"`
|
||||
}
|
||||
type HttpClientConfig struct {
|
||||
Servers []*HttpRemoteConfig `json:"servers"`
|
||||
type HTTPClientConfig struct {
|
||||
Servers []*HTTPRemoteConfig `json:"servers"`
|
||||
}
|
||||
|
||||
func (v *HttpClientConfig) Build() (proto.Message, error) {
|
||||
func (v *HTTPClientConfig) Build() (proto.Message, error) {
|
||||
config := new(http.ClientConfig)
|
||||
config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
|
||||
for idx, serverConfig := range v.Servers {
|
||||
@ -67,7 +67,7 @@ func (v *HttpClientConfig) Build() (proto.Message, error) {
|
||||
if err := json.Unmarshal(rawUser, user); err != nil {
|
||||
return nil, newError("failed to parse HTTP user").Base(err).AtError()
|
||||
}
|
||||
account := new(HttpAccount)
|
||||
account := new(HTTPAccount)
|
||||
if err := json.Unmarshal(rawUser, account); err != nil {
|
||||
return nil, newError("failed to parse HTTP account").Base(err).AtError()
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"v2ray.com/core/proxy/http"
|
||||
)
|
||||
|
||||
func TestHttpServerConfig(t *testing.T) {
|
||||
func TestHTTPServerConfig(t *testing.T) {
|
||||
creator := func() Buildable {
|
||||
return new(HttpServerConfig)
|
||||
return new(HTTPServerConfig)
|
||||
}
|
||||
|
||||
runMultiTestCase(t, []TestCase{
|
||||
|
@ -93,5 +93,4 @@ func TestReader1(t *testing.T) {
|
||||
t.Error("got ", string(target), " want ", testCase.output)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func TestBufferSize(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
bs := int32(c.Input)
|
||||
bs := c.Input
|
||||
pConf := Policy{
|
||||
BufferSize: &bs,
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"v2ray.com/core/app/router"
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/platform/filesystem"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
)
|
||||
|
||||
type RouterRulesConfig struct {
|
||||
@ -67,10 +67,15 @@ func (c *RouterConfig) Build() (*router.Config, error) {
|
||||
config := new(router.Config)
|
||||
config.DomainStrategy = c.getDomainStrategy()
|
||||
|
||||
rawRuleList := c.RuleList
|
||||
if c.Settings != nil {
|
||||
rawRuleList = append(c.RuleList, c.Settings.RuleList...)
|
||||
var rawRuleList []json.RawMessage
|
||||
if c != nil {
|
||||
rawRuleList = c.RuleList
|
||||
if c.Settings != nil {
|
||||
c.RuleList = append(c.RuleList, c.Settings.RuleList...)
|
||||
rawRuleList = c.RuleList
|
||||
}
|
||||
}
|
||||
|
||||
for _, rawRule := range rawRuleList {
|
||||
rule, err := ParseRule(rawRule)
|
||||
if err != nil {
|
||||
@ -290,15 +295,19 @@ func parseDomainRule(domain string) ([]*router.Domain, error) {
|
||||
case strings.HasPrefix(domain, "regexp:"):
|
||||
domainRule.Type = router.Domain_Regex
|
||||
domainRule.Value = domain[7:]
|
||||
|
||||
case strings.HasPrefix(domain, "domain:"):
|
||||
domainRule.Type = router.Domain_Domain
|
||||
domainRule.Value = domain[7:]
|
||||
|
||||
case strings.HasPrefix(domain, "full:"):
|
||||
domainRule.Type = router.Domain_Full
|
||||
domainRule.Value = domain[5:]
|
||||
|
||||
case strings.HasPrefix(domain, "keyword:"):
|
||||
domainRule.Type = router.Domain_Plain
|
||||
domainRule.Value = domain[8:]
|
||||
|
||||
case strings.HasPrefix(domain, "dotless:"):
|
||||
domainRule.Type = router.Domain_Regex
|
||||
switch substr := domain[8:]; {
|
||||
@ -309,6 +318,7 @@ func parseDomainRule(domain string) ([]*router.Domain, error) {
|
||||
default:
|
||||
return nil, newError("substr in dotless rule should not contain a dot: ", substr)
|
||||
}
|
||||
|
||||
default:
|
||||
domainRule.Type = router.Domain_Plain
|
||||
domainRule.Value = domain
|
||||
@ -403,15 +413,16 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
||||
}
|
||||
|
||||
rule := new(router.RoutingRule)
|
||||
if len(rawFieldRule.OutboundTag) > 0 {
|
||||
switch {
|
||||
case len(rawFieldRule.OutboundTag) > 0:
|
||||
rule.TargetTag = &router.RoutingRule_Tag{
|
||||
Tag: rawFieldRule.OutboundTag,
|
||||
}
|
||||
} else if len(rawFieldRule.BalancerTag) > 0 {
|
||||
case len(rawFieldRule.BalancerTag) > 0:
|
||||
rule.TargetTag = &router.RoutingRule_BalancingTag{
|
||||
BalancingTag: rawFieldRule.BalancerTag,
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
return nil, newError("neither outboundTag nor balancerTag is specified in routing rule")
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ func (v *SocksServerConfig) Build() (proto.Message, error) {
|
||||
case AuthMethodUserPass:
|
||||
config.AuthType = socks.AuthType_PASSWORD
|
||||
default:
|
||||
//newError("unknown socks auth method: ", v.AuthMethod, ". Default to noauth.").AtWarning().WriteToLog()
|
||||
// newError("unknown socks auth method: ", v.AuthMethod, ". Default to noauth.").AtWarning().WriteToLog()
|
||||
config.AuthType = socks.AuthType_NO_AUTH
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ func (DTLSAuthenticator) Build() (proto.Message, error) {
|
||||
return new(tls.PacketConfig), nil
|
||||
}
|
||||
|
||||
type HTTPAuthenticatorRequest struct {
|
||||
type AuthenticatorRequest struct {
|
||||
Version string `json:"version"`
|
||||
Method string `json:"method"`
|
||||
Path StringList `json:"path"`
|
||||
@ -72,7 +72,7 @@ func sortMapKeys(m map[string]*StringList) []string {
|
||||
return keys
|
||||
}
|
||||
|
||||
func (v *HTTPAuthenticatorRequest) Build() (*http.RequestConfig, error) {
|
||||
func (v *AuthenticatorRequest) Build() (*http.RequestConfig, error) {
|
||||
config := &http.RequestConfig{
|
||||
Uri: []string{"/"},
|
||||
Header: []*http.Header{
|
||||
@ -132,14 +132,14 @@ func (v *HTTPAuthenticatorRequest) Build() (*http.RequestConfig, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type HTTPAuthenticatorResponse struct {
|
||||
type AuthenticatorResponse struct {
|
||||
Version string `json:"version"`
|
||||
Status string `json:"status"`
|
||||
Reason string `json:"reason"`
|
||||
Headers map[string]*StringList `json:"headers"`
|
||||
}
|
||||
|
||||
func (v *HTTPAuthenticatorResponse) Build() (*http.ResponseConfig, error) {
|
||||
func (v *AuthenticatorResponse) Build() (*http.ResponseConfig, error) {
|
||||
config := &http.ResponseConfig{
|
||||
Header: []*http.Header{
|
||||
{
|
||||
@ -200,12 +200,12 @@ func (v *HTTPAuthenticatorResponse) Build() (*http.ResponseConfig, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type HTTPAuthenticator struct {
|
||||
Request HTTPAuthenticatorRequest `json:"request"`
|
||||
Response HTTPAuthenticatorResponse `json:"response"`
|
||||
type Authenticator struct {
|
||||
Request AuthenticatorRequest `json:"request"`
|
||||
Response AuthenticatorResponse `json:"response"`
|
||||
}
|
||||
|
||||
func (v *HTTPAuthenticator) Build() (proto.Message, error) {
|
||||
func (v *Authenticator) Build() (proto.Message, error) {
|
||||
config := new(http.Config)
|
||||
requestConfig, err := v.Request.Build()
|
||||
if err != nil {
|
||||
|
@ -31,7 +31,7 @@ var (
|
||||
|
||||
tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||
"none": func() interface{} { return new(NoOpConnectionAuthenticator) },
|
||||
"http": func() interface{} { return new(HTTPAuthenticator) },
|
||||
"http": func() interface{} { return new(Authenticator) },
|
||||
}, "type", "")
|
||||
)
|
||||
|
||||
@ -473,7 +473,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
ProtocolName: "tcp",
|
||||
}
|
||||
if c.Network != nil {
|
||||
protocol, err := (*c.Network).Build()
|
||||
protocol, err := c.Network.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/golang/protobuf/proto" // nolint: staticcheck
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/protocol"
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
var (
|
||||
inboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||
"dokodemo-door": func() interface{} { return new(DokodemoConfig) },
|
||||
"http": func() interface{} { return new(HttpServerConfig) },
|
||||
"http": func() interface{} { return new(HTTPServerConfig) },
|
||||
"shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) },
|
||||
"socks": func() interface{} { return new(SocksServerConfig) },
|
||||
"vless": func() interface{} { return new(VLessInboundConfig) },
|
||||
@ -29,14 +29,14 @@ var (
|
||||
outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||
"blackhole": func() interface{} { return new(BlackholeConfig) },
|
||||
"freedom": func() interface{} { return new(FreedomConfig) },
|
||||
"http": func() interface{} { return new(HttpClientConfig) },
|
||||
"http": func() interface{} { return new(HTTPClientConfig) },
|
||||
"shadowsocks": func() interface{} { return new(ShadowsocksClientConfig) },
|
||||
"socks": func() interface{} { return new(SocksClientConfig) },
|
||||
"vless": func() interface{} { return new(VLessOutboundConfig) },
|
||||
"vmess": func() interface{} { return new(VMessOutboundConfig) },
|
||||
"trojan": func() interface{} { return new(TrojanClientConfig) },
|
||||
"mtproto": func() interface{} { return new(MTProtoClientConfig) },
|
||||
"dns": func() interface{} { return new(DnsOutboundConfig) },
|
||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
||||
ctllog = log.New(os.Stderr, "v2ctl> ", 0)
|
||||
@ -315,7 +315,7 @@ type Config struct {
|
||||
Port uint16 `json:"port"` // Port of this Point server. Deprecated.
|
||||
LogConfig *LogConfig `json:"log"`
|
||||
RouterConfig *RouterConfig `json:"routing"`
|
||||
DNSConfig *DnsConfig `json:"dns"`
|
||||
DNSConfig *DNSConfig `json:"dns"`
|
||||
InboundConfigs []InboundDetourConfig `json:"inbounds"`
|
||||
OutboundConfigs []OutboundDetourConfig `json:"outbounds"`
|
||||
InboundConfig *InboundDetourConfig `json:"inbound"` // Deprecated.
|
||||
@ -324,7 +324,7 @@ type Config struct {
|
||||
OutboundDetours []OutboundDetourConfig `json:"outboundDetour"` // Deprecated.
|
||||
Transport *TransportConfig `json:"transport"`
|
||||
Policy *PolicyConfig `json:"policy"`
|
||||
Api *ApiConfig `json:"api"`
|
||||
API *APIConfig `json:"api"`
|
||||
Stats *StatsConfig `json:"stats"`
|
||||
Reverse *ReverseConfig `json:"reverse"`
|
||||
}
|
||||
@ -353,7 +353,6 @@ func (c *Config) findOutboundTag(tag string) int {
|
||||
|
||||
// Override method accepts another Config overrides the current attribute
|
||||
func (c *Config) Override(o *Config, fn string) {
|
||||
|
||||
// only process the non-deprecated members
|
||||
|
||||
if o.LogConfig != nil {
|
||||
@ -371,8 +370,8 @@ func (c *Config) Override(o *Config, fn string) {
|
||||
if o.Policy != nil {
|
||||
c.Policy = o.Policy
|
||||
}
|
||||
if o.Api != nil {
|
||||
c.Api = o.Api
|
||||
if o.API != nil {
|
||||
c.API = o.API
|
||||
}
|
||||
if o.Stats != nil {
|
||||
c.Stats = o.Stats
|
||||
@ -460,8 +459,8 @@ func (c *Config) Build() (*core.Config, error) {
|
||||
},
|
||||
}
|
||||
|
||||
if c.Api != nil {
|
||||
apiConf, err := c.Api.Build()
|
||||
if c.API != nil {
|
||||
apiConf, err := c.API.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -384,10 +384,10 @@ func TestConfig_Override(t *testing.T) {
|
||||
&Config{
|
||||
LogConfig: &LogConfig{},
|
||||
RouterConfig: &RouterConfig{},
|
||||
DNSConfig: &DnsConfig{},
|
||||
DNSConfig: &DNSConfig{},
|
||||
Transport: &TransportConfig{},
|
||||
Policy: &PolicyConfig{},
|
||||
Api: &ApiConfig{},
|
||||
API: &APIConfig{},
|
||||
Stats: &StatsConfig{},
|
||||
Reverse: &ReverseConfig{},
|
||||
},
|
||||
@ -395,10 +395,10 @@ func TestConfig_Override(t *testing.T) {
|
||||
&Config{
|
||||
LogConfig: &LogConfig{},
|
||||
RouterConfig: &RouterConfig{},
|
||||
DNSConfig: &DnsConfig{},
|
||||
DNSConfig: &DNSConfig{},
|
||||
Transport: &TransportConfig{},
|
||||
Policy: &PolicyConfig{},
|
||||
Api: &ApiConfig{},
|
||||
API: &APIConfig{},
|
||||
Stats: &StatsConfig{},
|
||||
Reverse: &ReverseConfig{},
|
||||
},
|
||||
|
@ -33,12 +33,7 @@ type VLessInboundConfig struct {
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||
|
||||
config := new(inbound.Config)
|
||||
|
||||
if len(c.Clients) == 0 {
|
||||
//return nil, newError(`VLESS settings: "clients" is empty`)
|
||||
}
|
||||
config.Clients = make([]*protocol.User, len(c.Clients))
|
||||
for idx, rawUser := range c.Clients {
|
||||
user := new(protocol.User)
|
||||
@ -142,7 +137,6 @@ type VLessOutboundConfig struct {
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
||||
|
||||
config := new(outbound.Config)
|
||||
|
||||
if len(c.Vnext) == 0 {
|
||||
|
@ -16,13 +16,13 @@ import (
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
type ApiCommand struct{}
|
||||
type APICommand struct{}
|
||||
|
||||
func (c *ApiCommand) Name() string {
|
||||
func (c *APICommand) Name() string {
|
||||
return "api"
|
||||
}
|
||||
|
||||
func (c *ApiCommand) Description() Description {
|
||||
func (c *APICommand) Description() Description {
|
||||
return Description{
|
||||
Short: "Call V2Ray API",
|
||||
Usage: []string{
|
||||
@ -42,7 +42,7 @@ func (c *ApiCommand) Description() Description {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ApiCommand) Execute(args []string) error {
|
||||
func (c *APICommand) Execute(args []string) error {
|
||||
fs := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
|
||||
serverAddrPtr := fs.String("server", "127.0.0.1:8080", "Server address")
|
||||
@ -154,5 +154,5 @@ func callStatsService(ctx context.Context, conn *grpc.ClientConn, method string,
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(RegisterCommand(&ApiCommand{}))
|
||||
common.Must(RegisterCommand(&APICommand{}))
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func (c *CertificateCommand) Description() Description {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CertificateCommand) printJson(certificate *cert.Certificate) {
|
||||
func (c *CertificateCommand) printJSON(certificate *cert.Certificate) {
|
||||
certPEM, keyPEM := certificate.ToPEM()
|
||||
jCert := &jsonCert{
|
||||
Certificate: strings.Split(strings.TrimSpace(string(certPEM)), "\n"),
|
||||
@ -122,7 +122,7 @@ func (c *CertificateCommand) Execute(args []string) error {
|
||||
}
|
||||
|
||||
if *jsonOutput {
|
||||
c.printJson(cert)
|
||||
c.printJSON(cert)
|
||||
}
|
||||
|
||||
if len(*fileOutput) > 0 {
|
||||
|
@ -66,13 +66,15 @@ func (c *ConfigCommand) Execute(args []string) error {
|
||||
|
||||
// LoadArg loads one arg, maybe an remote url, or local file path
|
||||
func (c *ConfigCommand) LoadArg(arg string) (out io.Reader, err error) {
|
||||
|
||||
var data []byte
|
||||
if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
|
||||
switch {
|
||||
case strings.HasPrefix(arg, "http://"), strings.HasPrefix(arg, "https://"):
|
||||
data, err = FetchHTTPContent(arg)
|
||||
} else if arg == "stdin:" {
|
||||
|
||||
case arg == "stdin:":
|
||||
data, err = ioutil.ReadAll(os.Stdin)
|
||||
} else {
|
||||
|
||||
default:
|
||||
data, err = ioutil.ReadFile(arg)
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@ func (c *FetchCommand) Execute(args []string) error {
|
||||
|
||||
// FetchHTTPContent dials https for remote content
|
||||
func FetchHTTPContent(target string) ([]byte, error) {
|
||||
|
||||
parsedTarget, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return nil, newError("invalid URL: ", target).Base(err)
|
||||
|
@ -10,13 +10,13 @@ import (
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
type TlsPingCommand struct{}
|
||||
type TLSPingCommand struct{}
|
||||
|
||||
func (c *TlsPingCommand) Name() string {
|
||||
func (c *TLSPingCommand) Name() string {
|
||||
return "tlsping"
|
||||
}
|
||||
|
||||
func (c *TlsPingCommand) Description() Description {
|
||||
func (c *TLSPingCommand) Description() Description {
|
||||
return Description{
|
||||
Short: "Ping the domain with TLS handshake",
|
||||
Usage: []string{"v2ctl tlsping <domain> --ip <ip>"},
|
||||
@ -32,7 +32,7 @@ func printCertificates(certs []*x509.Certificate) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *TlsPingCommand) Execute(args []string) error {
|
||||
func (c *TLSPingCommand) Execute(args []string) error {
|
||||
fs := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
|
||||
ipStr := fs.String("ip", "", "IP address of the domain")
|
||||
|
||||
@ -115,5 +115,5 @@ func (c *TlsPingCommand) Execute(args []string) error {
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(RegisterCommand(&TlsPingCommand{}))
|
||||
common.Must(RegisterCommand(&TLSPingCommand{}))
|
||||
}
|
||||
|
@ -2,8 +2,9 @@ package control
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"github.com/xiaokangwang/VSign/signerVerify"
|
||||
"os"
|
||||
|
||||
"github.com/xiaokangwang/VSign/signerVerify"
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
|
11
main/confloader/external/external.go
vendored
11
main/confloader/external/external.go
vendored
@ -18,13 +18,15 @@ import (
|
||||
)
|
||||
|
||||
func ConfigLoader(arg string) (out io.Reader, err error) {
|
||||
|
||||
var data []byte
|
||||
if strings.HasPrefix(arg, "http://") || strings.HasPrefix(arg, "https://") {
|
||||
switch {
|
||||
case strings.HasPrefix(arg, "http://"), strings.HasPrefix(arg, "https://"):
|
||||
data, err = FetchHTTPContent(arg)
|
||||
} else if arg == "stdin:" {
|
||||
|
||||
case arg == "stdin:":
|
||||
data, err = ioutil.ReadAll(os.Stdin)
|
||||
} else {
|
||||
|
||||
default:
|
||||
data, err = ioutil.ReadFile(arg)
|
||||
}
|
||||
|
||||
@ -36,7 +38,6 @@ func ConfigLoader(arg string) (out io.Reader, err error) {
|
||||
}
|
||||
|
||||
func FetchHTTPContent(target string) ([]byte, error) {
|
||||
|
||||
parsedTarget, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return nil, newError("invalid URL: ", target).Base(err)
|
||||
|
@ -1,7 +1,8 @@
|
||||
package debug
|
||||
|
||||
import _ "net/http/pprof"
|
||||
import "net/http"
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func init() {
|
||||
go func() {
|
||||
|
@ -70,11 +70,9 @@ func getConfigFilePath() (cmdarg.Arg, error) {
|
||||
if dirExists(configDir) {
|
||||
log.Println("Using confdir from arg:", configDir)
|
||||
readConfDir(configDir)
|
||||
} else {
|
||||
if envConfDir := platform.GetConfDirPath(); dirExists(envConfDir) {
|
||||
log.Println("Using confdir from env:", envConfDir)
|
||||
readConfDir(envConfDir)
|
||||
}
|
||||
} else if envConfDir := platform.GetConfDirPath(); dirExists(envConfDir) {
|
||||
log.Println("Using confdir from env:", envConfDir)
|
||||
readConfDir(envConfDir)
|
||||
}
|
||||
|
||||
if len(configFiles) > 0 {
|
||||
@ -134,7 +132,6 @@ func printVersion() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
flag.Parse()
|
||||
|
||||
printVersion()
|
||||
|
@ -1,7 +1,6 @@
|
||||
// +build !confonly
|
||||
|
||||
// Package blackhole is an outbound handler that blocks all connections.
|
||||
|
||||
package blackhole
|
||||
|
||||
//go:generate go run v2ray.com/core/common/errors/errorgen
|
||||
|
@ -19,6 +19,7 @@ func TestHTTPResponse(t *testing.T) {
|
||||
reader := bufio.NewReader(buffer)
|
||||
response, err := http.ReadResponse(reader, nil)
|
||||
common.Must(err)
|
||||
|
||||
if response.StatusCode != 403 {
|
||||
t.Error("expected status code 403, but got ", response.StatusCode)
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
}
|
||||
|
||||
for _, q := range r.Question {
|
||||
if q.Name == "google.com." && q.Qtype == dns.TypeA {
|
||||
switch {
|
||||
case q.Name == "google.com." && q.Qtype == dns.TypeA:
|
||||
if clientIP == nil {
|
||||
rr, _ := dns.NewRR("google.com. IN A 8.8.8.8")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
@ -52,18 +53,22 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
||||
rr, _ := dns.NewRR("google.com. IN A 8.8.4.4")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
}
|
||||
} else if q.Name == "facebook.com." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "facebook.com." && q.Qtype == dns.TypeA:
|
||||
rr, _ := dns.NewRR("facebook.com. IN A 9.9.9.9")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA {
|
||||
|
||||
case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeA:
|
||||
rr, err := dns.NewRR("ipv6.google.com. IN A 8.8.8.7")
|
||||
common.Must(err)
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA {
|
||||
|
||||
case q.Name == "ipv6.google.com." && q.Qtype == dns.TypeAAAA:
|
||||
rr, err := dns.NewRR("ipv6.google.com. IN AAAA 2001:4860:4860::8888")
|
||||
common.Must(err)
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
} else if q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA {
|
||||
|
||||
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
|
||||
ans.MsgHdr.Rcode = dns.RcodeNameError
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn in
|
||||
if network == net.Network_TCP {
|
||||
writer = buf.NewWriter(conn)
|
||||
} else {
|
||||
//if we are in TPROXY mode, use linux's udp forging functionality
|
||||
// if we are in TPROXY mode, use linux's udp forging functionality
|
||||
if !destinationOverridden {
|
||||
writer = &buf.SequentialWriter{Writer: conn}
|
||||
} else {
|
||||
|
@ -137,7 +137,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
if err != nil {
|
||||
return newError("failed to open connection to ", destination).Base(err)
|
||||
}
|
||||
defer conn.Close() // nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
plcy := h.policy()
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
@ -103,7 +103,7 @@ Start:
|
||||
if err != nil {
|
||||
trace := newError("failed to read http request").Base(err)
|
||||
if errors.Cause(err) != io.EOF && !isTimeout(errors.Cause(err)) {
|
||||
trace.AtWarning() // nolint: errcheck
|
||||
trace.AtWarning()
|
||||
}
|
||||
return trace
|
||||
}
|
||||
@ -159,7 +159,7 @@ Start:
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Server) handleConnect(ctx context.Context, request *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher routing.Dispatcher) error {
|
||||
func (s *Server) handleConnect(ctx context.Context, _ *http.Request, reader *bufio.Reader, conn internet.Connection, dest net.Destination, dispatcher routing.Dispatcher) error {
|
||||
_, err := conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n"))
|
||||
if err != nil {
|
||||
return newError("failed to write back OK response").Base(err)
|
||||
@ -263,7 +263,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
|
||||
}
|
||||
|
||||
// Plain HTTP request is not a stream. The request always finishes before response. Hense request has to be closed later.
|
||||
defer common.Close(link.Writer) // nolint: errcheck
|
||||
defer common.Close(link.Writer)
|
||||
var result error = errWaitAnother
|
||||
|
||||
requestDone := func() error {
|
||||
|
@ -34,7 +34,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
if err != nil {
|
||||
return newError("failed to dial to ", dest).Base(err).AtWarning()
|
||||
}
|
||||
defer conn.Close() // nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
sc := SessionContextFromContext(ctx)
|
||||
auth := NewAuthentication(sc)
|
||||
|
@ -136,7 +136,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
}
|
||||
|
||||
if request.Command == protocol.RequestCommandUDP {
|
||||
|
||||
writer := &buf.SequentialWriter{Writer: &UDPWriter{
|
||||
Writer: conn,
|
||||
Request: request,
|
||||
|
@ -6,14 +6,13 @@ import (
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"v2ray.com/core/common/dice"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
"v2ray.com/core/common/buf"
|
||||
"v2ray.com/core/common/dice"
|
||||
"v2ray.com/core/common/net"
|
||||
"v2ray.com/core/common/protocol"
|
||||
)
|
||||
@ -35,7 +34,7 @@ var addrParser = protocol.NewAddressParser(
|
||||
func ReadTCPSession(user *protocol.MemoryUser, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) {
|
||||
account := user.Account.(*MemoryAccount)
|
||||
|
||||
hashkdf := hmac.New(func() hash.Hash { return sha256.New() }, []byte("SSBSKDF"))
|
||||
hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
|
||||
hashkdf.Write(account.Key)
|
||||
|
||||
behaviorSeed := crc32.ChecksumIEEE(hashkdf.Sum(nil))
|
||||
|
@ -133,7 +133,6 @@ func TestTCPRequest(t *testing.T) {
|
||||
for _, test := range cases {
|
||||
runTest(test.request, test.payload)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestUDPReaderWriter(t *testing.T) {
|
||||
|
@ -127,7 +127,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
if err != nil {
|
||||
return newError("failed to create UDP connection").Base(err)
|
||||
}
|
||||
defer udpConn.Close() // nolint: errcheck
|
||||
defer udpConn.Close()
|
||||
requestFunc = func() error {
|
||||
defer timer.SetTimeout(p.Timeouts.DownlinkOnly)
|
||||
return buf.Copy(link.Reader, &buf.SequentialWriter{Writer: NewUDPWriter(request, udpConn)}, buf.UpdateActivity(timer))
|
||||
|
@ -26,7 +26,7 @@ const (
|
||||
socks4RequestRejected = 91
|
||||
|
||||
authNotRequired = 0x00
|
||||
//authGssAPI = 0x01
|
||||
// authGssAPI = 0x01
|
||||
authPassword = 0x02
|
||||
authNoMatchingMethod = 0xFF
|
||||
|
||||
@ -47,7 +47,7 @@ type ServerSession struct {
|
||||
|
||||
func (s *ServerSession) handshake4(cmd byte, reader io.Reader, writer io.Writer) (*protocol.RequestHeader, error) {
|
||||
if s.config.AuthType == AuthType_PASSWORD {
|
||||
writeSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0)) // nolint: errcheck
|
||||
writeSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0))
|
||||
return nil, newError("socks 4 is not allowed when auth is required.")
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ func (s *ServerSession) handshake4(cmd byte, reader io.Reader, writer io.Writer)
|
||||
}
|
||||
return request, nil
|
||||
default:
|
||||
writeSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0)) // nolint: errcheck
|
||||
writeSocks4Response(writer, socks4RequestRejected, net.AnyIP, net.Port(0))
|
||||
return nil, newError("unsupported command: ", cmd)
|
||||
}
|
||||
}
|
||||
@ -108,7 +108,7 @@ func (s *ServerSession) auth5(nMethod byte, reader io.Reader, writer io.Writer)
|
||||
}
|
||||
|
||||
if !hasAuthMethod(expectedAuth, buffer.BytesRange(0, int32(nMethod))) {
|
||||
writeSocks5AuthenticationResponse(writer, socks5Version, authNoMatchingMethod) // nolint: errcheck
|
||||
writeSocks5AuthenticationResponse(writer, socks5Version, authNoMatchingMethod)
|
||||
return "", newError("no matching auth method")
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ func (s *ServerSession) auth5(nMethod byte, reader io.Reader, writer io.Writer)
|
||||
}
|
||||
|
||||
if !s.config.HasAccount(username, password) {
|
||||
writeSocks5AuthenticationResponse(writer, 0x01, 0xFF) // nolint: errcheck
|
||||
writeSocks5AuthenticationResponse(writer, 0x01, 0xFF)
|
||||
return "", newError("invalid username or password")
|
||||
}
|
||||
|
||||
@ -166,15 +166,15 @@ func (s *ServerSession) handshake5(nMethod byte, reader io.Reader, writer io.Wri
|
||||
request.Command = protocol.RequestCommandTCP
|
||||
case cmdUDPPort:
|
||||
if !s.config.UdpEnabled {
|
||||
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0)) // nolint: errcheck
|
||||
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0))
|
||||
return nil, newError("UDP is not enabled.")
|
||||
}
|
||||
request.Command = protocol.RequestCommandUDP
|
||||
case cmdTCPBind:
|
||||
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0)) // nolint: errcheck
|
||||
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0))
|
||||
return nil, newError("TCP bind is not supported.")
|
||||
default:
|
||||
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0)) // nolint: errcheck
|
||||
writeSocks5Response(writer, statusCmdNotSupport, net.AnyIP, net.Port(0))
|
||||
return nil, newError("unknown command ", cmd)
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn internet.Connection,
|
||||
newError("failed to write UDP response").AtWarning().Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
|
||||
conn.Write(udpMessage.Bytes()) // nolint: errcheck
|
||||
conn.Write(udpMessage.Bytes())
|
||||
})
|
||||
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Source.IsValid() {
|
||||
|
@ -49,7 +49,7 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
}
|
||||
|
||||
// Process implements OutboundHandler.Process().
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error { // nolint: funlen
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
return newError("target not specified")
|
||||
@ -60,7 +60,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
var server *protocol.ServerSpec
|
||||
var conn internet.Connection
|
||||
|
||||
err := retry.ExponentialBackoff(5, 100).On(func() error { // nolint: gomnd
|
||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||
server = c.serverPicker.PickServer()
|
||||
rawConn, err := dialer.Dial(ctx, server.Destination())
|
||||
if err != nil {
|
||||
@ -101,7 +101,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
}
|
||||
|
||||
// write some request payload to buffer
|
||||
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout { // nolint: lll,gomnd
|
||||
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
|
||||
return newError("failed to write A reqeust payload").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { // nolint: lll
|
||||
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewClient(ctx, config.(*ClientConfig))
|
||||
}))
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ var (
|
||||
crlf = []byte{'\r', '\n'}
|
||||
|
||||
addrParser = protocol.NewAddressParser(
|
||||
protocol.AddressFamilyByte(0x01, net.AddressFamilyIPv4), // nolint: gomnd
|
||||
protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6), // nolint: gomnd
|
||||
protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain), // nolint: gomnd
|
||||
protocol.AddressFamilyByte(0x01, net.AddressFamilyIPv4),
|
||||
protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6),
|
||||
protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain),
|
||||
)
|
||||
)
|
||||
|
||||
@ -129,7 +129,7 @@ func (w *PacketWriter) WriteMultiBufferWithMetadata(mb buf.MultiBuffer, dest net
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) { // nolint: unparam
|
||||
func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) {
|
||||
buffer := buf.StackNew()
|
||||
defer buffer.Release()
|
||||
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { // nolint: lll
|
||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewServer(ctx, config.(*ServerConfig))
|
||||
}))
|
||||
}
|
||||
@ -91,8 +91,7 @@ func (s *Server) Network() []net.Network {
|
||||
}
|
||||
|
||||
// Process implements proxy.Inbound.Process().
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error { // nolint: funlen,lll
|
||||
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||
sid := session.ExportIDToError(ctx)
|
||||
|
||||
iConn := conn
|
||||
@ -125,7 +124,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
||||
isfb := apfb != nil
|
||||
|
||||
shouldFallback := false
|
||||
if firstLen < 58 || first.Byte(56) != '\r' { // nolint: gomnd
|
||||
if firstLen < 58 || first.Byte(56) != '\r' {
|
||||
// invalid protocol
|
||||
err = newError("not trojan protocol")
|
||||
log.Record(&log.AccessMessage{
|
||||
@ -137,7 +136,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
||||
|
||||
shouldFallback = true
|
||||
} else {
|
||||
user = s.validator.Get(hexString(first.BytesTo(56))) // nolint: gomnd
|
||||
user = s.validator.Get(hexString(first.BytesTo(56)))
|
||||
if user == nil {
|
||||
// invalid user, let's fallback
|
||||
err = newError("not a valid user")
|
||||
@ -199,7 +198,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
|
||||
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher)
|
||||
}
|
||||
|
||||
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error { // nolint: lll
|
||||
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
|
||||
udpServer := udp.NewDispatcher(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||
common.Must(clientWriter.WriteMultiBufferWithMetadata(buf.MultiBuffer{packet.Payload}, packet.Source))
|
||||
})
|
||||
@ -277,7 +276,7 @@ func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Sess
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err error, sessionPolicy policy.Session, connection internet.Connection, iConn internet.Connection, apfb map[string]map[string]*Fallback, first *buf.Buffer, firstLen int64, reader buf.Reader) error { // nolint: lll
|
||||
func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err error, sessionPolicy policy.Session, connection internet.Connection, iConn internet.Connection, apfb map[string]map[string]*Fallback, first *buf.Buffer, firstLen int64, reader buf.Reader) error {
|
||||
if err := connection.SetReadDeadline(time.Time{}); err != nil {
|
||||
newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
|
||||
}
|
||||
|
@ -13,10 +13,8 @@ import (
|
||||
)
|
||||
|
||||
func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error {
|
||||
|
||||
switch addons.Flow {
|
||||
case vless.XRO, vless.XRD:
|
||||
|
||||
bytes, err := proto.Marshal(addons)
|
||||
if err != nil {
|
||||
return newError("failed to marshal addons protobuf value").Base(err)
|
||||
@ -27,30 +25,23 @@ func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error {
|
||||
if _, err := buffer.Write(bytes); err != nil {
|
||||
return newError("failed to write addons protobuf value").Base(err)
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
if err := buffer.WriteByte(0); err != nil {
|
||||
return newError("failed to write addons protobuf length").Base(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
|
||||
|
||||
addons := new(Addons)
|
||||
|
||||
buffer.Clear()
|
||||
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
||||
return nil, newError("failed to read addons protobuf length").Base(err)
|
||||
}
|
||||
|
||||
if length := int32(buffer.Byte(0)); length != 0 {
|
||||
|
||||
buffer.Clear()
|
||||
if _, err := buffer.ReadFullFrom(reader, length); err != nil {
|
||||
return nil, newError("failed to read addons protobuf value").Base(err)
|
||||
@ -63,45 +54,32 @@ func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
|
||||
// Verification.
|
||||
switch addons.Flow {
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return addons, nil
|
||||
|
||||
}
|
||||
|
||||
// EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
|
||||
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, addons *Addons) buf.Writer {
|
||||
|
||||
switch addons.Flow {
|
||||
default:
|
||||
|
||||
if request.Command == protocol.RequestCommandUDP {
|
||||
return NewMultiLengthPacketWriter(writer.(buf.Writer))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return buf.NewWriter(writer)
|
||||
|
||||
}
|
||||
|
||||
// DecodeBodyAddons returns a Reader from which caller can fetch decrypted body.
|
||||
func DecodeBodyAddons(reader io.Reader, request *protocol.RequestHeader, addons *Addons) buf.Reader {
|
||||
|
||||
switch addons.Flow {
|
||||
default:
|
||||
|
||||
if request.Command == protocol.RequestCommandUDP {
|
||||
return NewLengthPacketReader(reader)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return buf.NewReader(reader)
|
||||
|
||||
}
|
||||
|
||||
func NewMultiLengthPacketWriter(writer buf.Writer) *MultiLengthPacketWriter {
|
||||
@ -157,7 +135,7 @@ type LengthPacketWriter struct {
|
||||
|
||||
func (w *LengthPacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
length := mb.Len() // none of mb is nil
|
||||
//fmt.Println("Write", length)
|
||||
// fmt.Println("Write", length)
|
||||
if length == 0 {
|
||||
return nil
|
||||
}
|
||||
@ -193,7 +171,7 @@ func (r *LengthPacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
return nil, newError("failed to read packet length").Base(err)
|
||||
}
|
||||
length := int32(r.cache[0])<<8 | int32(r.cache[1])
|
||||
//fmt.Println("Read", length)
|
||||
// fmt.Println("Read", length)
|
||||
mb := make(buf.MultiBuffer, 0, length/buf.Size+1)
|
||||
for length > 0 {
|
||||
size := length
|
||||
|
@ -26,7 +26,6 @@ var addrParser = protocol.NewAddressParser(
|
||||
|
||||
// EncodeRequestHeader writes encoded request header into the given writer.
|
||||
func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons) error {
|
||||
|
||||
buffer := buf.StackNew()
|
||||
defer buffer.Release()
|
||||
|
||||
@ -60,8 +59,7 @@ func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requ
|
||||
}
|
||||
|
||||
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
|
||||
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator *vless.Validator) (*protocol.RequestHeader, *Addons, error, bool) {
|
||||
|
||||
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator *vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
|
||||
buffer := buf.StackNew()
|
||||
defer buffer.Release()
|
||||
|
||||
@ -71,7 +69,7 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
||||
request.Version = first.Byte(0)
|
||||
} else {
|
||||
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
||||
return nil, nil, newError("failed to read request version").Base(err), false
|
||||
return nil, nil, false, newError("failed to read request version").Base(err)
|
||||
}
|
||||
request.Version = buffer.Byte(0)
|
||||
}
|
||||
@ -86,13 +84,13 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
||||
} else {
|
||||
buffer.Clear()
|
||||
if _, err := buffer.ReadFullFrom(reader, 16); err != nil {
|
||||
return nil, nil, newError("failed to read request user id").Base(err), false
|
||||
return nil, nil, false, newError("failed to read request user id").Base(err)
|
||||
}
|
||||
copy(id[:], buffer.Bytes())
|
||||
}
|
||||
|
||||
if request.User = validator.Get(id); request.User == nil {
|
||||
return nil, nil, newError("invalid request user id"), isfb
|
||||
return nil, nil, isfb, newError("invalid request user id")
|
||||
}
|
||||
|
||||
if isfb {
|
||||
@ -101,12 +99,12 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
||||
|
||||
requestAddons, err := DecodeHeaderAddons(&buffer, reader)
|
||||
if err != nil {
|
||||
return nil, nil, newError("failed to decode request header addons").Base(err), false
|
||||
return nil, nil, false, newError("failed to decode request header addons").Base(err)
|
||||
}
|
||||
|
||||
buffer.Clear()
|
||||
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
||||
return nil, nil, newError("failed to read request command").Base(err), false
|
||||
return nil, nil, false, newError("failed to read request command").Base(err)
|
||||
}
|
||||
|
||||
request.Command = protocol.RequestCommand(buffer.Byte(0))
|
||||
@ -120,24 +118,17 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
||||
request.Port = port
|
||||
}
|
||||
}
|
||||
|
||||
if request.Address == nil {
|
||||
return nil, nil, newError("invalid request address"), false
|
||||
return nil, nil, false, newError("invalid request address")
|
||||
}
|
||||
|
||||
return request, requestAddons, nil, false
|
||||
|
||||
return request, requestAddons, false, nil
|
||||
default:
|
||||
|
||||
return nil, nil, newError("invalid request version"), isfb
|
||||
|
||||
return nil, nil, isfb, newError("invalid request version")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// EncodeResponseHeader writes encoded response header into the given writer.
|
||||
func EncodeResponseHeader(writer io.Writer, request *protocol.RequestHeader, responseAddons *Addons) error {
|
||||
|
||||
buffer := buf.StackNew()
|
||||
defer buffer.Release()
|
||||
|
||||
@ -158,7 +149,6 @@ func EncodeResponseHeader(writer io.Writer, request *protocol.RequestHeader, res
|
||||
|
||||
// DecodeResponseHeader decodes and returns (if successful) a ResponseHeader from an input stream.
|
||||
func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*Addons, error) {
|
||||
|
||||
buffer := buf.StackNew()
|
||||
defer buffer.Release()
|
||||
|
||||
|
@ -46,7 +46,7 @@ func TestRequestSerialization(t *testing.T) {
|
||||
Validator := new(vless.Validator)
|
||||
Validator.Add(user)
|
||||
|
||||
actualRequest, actualAddons, err, _ := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
common.Must(err)
|
||||
|
||||
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
|
||||
@ -83,7 +83,7 @@ func TestInvalidRequest(t *testing.T) {
|
||||
Validator := new(vless.Validator)
|
||||
Validator.Add(user)
|
||||
|
||||
_, _, err, _ := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
_, _, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
if err == nil {
|
||||
t.Error("nil error")
|
||||
}
|
||||
@ -114,7 +114,7 @@ func TestMuxRequest(t *testing.T) {
|
||||
Validator := new(vless.Validator)
|
||||
Validator.Add(user)
|
||||
|
||||
actualRequest, actualAddons, err, _ := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
common.Must(err)
|
||||
|
||||
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
|
||||
|
@ -64,12 +64,11 @@ type Handler struct {
|
||||
validator *vless.Validator
|
||||
dns dns.Client
|
||||
fallbacks map[string]map[string]*Fallback // or nil
|
||||
//regexps map[string]*regexp.Regexp // or nil
|
||||
// regexps map[string]*regexp.Regexp // or nil
|
||||
}
|
||||
|
||||
// New creates a new VLess inbound handler.
|
||||
func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
|
||||
|
||||
v := core.MustFromContext(ctx)
|
||||
handler := &Handler{
|
||||
inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager),
|
||||
@ -90,7 +89,7 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
|
||||
|
||||
if config.Fallbacks != nil {
|
||||
handler.fallbacks = make(map[string]map[string]*Fallback)
|
||||
//handler.regexps = make(map[string]*regexp.Regexp)
|
||||
// handler.regexps = make(map[string]*regexp.Regexp)
|
||||
for _, fb := range config.Fallbacks {
|
||||
if handler.fallbacks[fb.Alpn] == nil {
|
||||
handler.fallbacks[fb.Alpn] = make(map[string]*Fallback)
|
||||
@ -144,9 +143,7 @@ func (*Handler) Network() []net.Network {
|
||||
|
||||
// Process implements proxy.Inbound.Process().
|
||||
func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher routing.Dispatcher) error {
|
||||
|
||||
sid := session.ExportIDToError(ctx)
|
||||
|
||||
iConn := connection
|
||||
if statConn, ok := iConn.(*internet.StatCouterConnection); ok {
|
||||
iConn = statConn.Connection
|
||||
@ -178,11 +175,10 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
||||
if isfb && firstLen < 18 {
|
||||
err = newError("fallback directly")
|
||||
} else {
|
||||
request, requestAddons, err, isfb = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
|
||||
request, requestAddons, isfb, err = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
if isfb {
|
||||
if err := connection.SetReadDeadline(time.Time{}); err != nil {
|
||||
newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid)
|
||||
@ -271,7 +267,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
||||
}); err != nil {
|
||||
return newError("failed to dial to " + fb.Dest).Base(err).AtWarning()
|
||||
}
|
||||
defer conn.Close() // nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
serverReader := buf.NewReader(conn)
|
||||
serverWriter := buf.NewWriter(conn)
|
||||
@ -303,6 +299,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
||||
} else {
|
||||
pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n"))
|
||||
}
|
||||
|
||||
case 2:
|
||||
pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21")) // signature + v2 + PROXY
|
||||
if ipv4 {
|
||||
@ -372,7 +369,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
||||
account := request.User.Account.(*vless.MemoryAccount)
|
||||
|
||||
responseAddons := &encoding.Addons{
|
||||
//Flow: requestAddons.Flow,
|
||||
// Flow: requestAddons.Flow,
|
||||
}
|
||||
|
||||
switch requestAddons.Flow {
|
||||
@ -473,7 +470,6 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i
|
||||
// Indicates the end of response payload.
|
||||
switch responseAddons.Flow {
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -52,7 +52,6 @@ type Handler struct {
|
||||
|
||||
// New creates a new VLess outbound handler.
|
||||
func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||
|
||||
serverList := protocol.NewServerList()
|
||||
for _, rec := range config.Vnext {
|
||||
s, err := protocol.NewServerSpecFromPB(rec)
|
||||
@ -74,7 +73,6 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||
|
||||
// Process implements proxy.Outbound.Process().
|
||||
func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
|
||||
var rec *protocol.ServerSpec
|
||||
var conn internet.Connection
|
||||
|
||||
@ -89,7 +87,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}); err != nil {
|
||||
return newError("failed to find an available destination").Base(err).AtWarning()
|
||||
}
|
||||
defer conn.Close() // nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
iConn := conn
|
||||
if statConn, ok := iConn.(*internet.StatCouterConnection); ok {
|
||||
@ -193,9 +191,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
// Indicates the end of request payload.
|
||||
switch requestAddons.Flow {
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,16 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
antiReplayWindow "v2ray.com/core/common/antireplay"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("user do not exist")
|
||||
ErrReplay = errors.New("replayed request")
|
||||
)
|
||||
|
||||
func CreateAuthID(cmdKey []byte, time int64) [16]byte {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
common.Must(binary.Write(buf, binary.BigEndian, time))
|
||||
@ -32,7 +38,7 @@ func CreateAuthID(cmdKey []byte, time int64) [16]byte {
|
||||
}
|
||||
|
||||
func NewCipherFromKey(cmdKey []byte) cipher.Block {
|
||||
aesBlock, err := aes.NewCipher(KDF16(cmdKey, KDFSaltConst_AuthIDEncryptionKey))
|
||||
aesBlock, err := aes.NewCipher(KDF16(cmdKey, KDFSaltConstAuthIDEncryptionKey))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -88,10 +94,9 @@ func (a *AuthIDDecoderHolder) RemoveUser(key [16]byte) {
|
||||
delete(a.aidhi, string(key[:]))
|
||||
}
|
||||
|
||||
func (a *AuthIDDecoderHolder) Match(AuthID [16]byte) (interface{}, error) {
|
||||
func (a *AuthIDDecoderHolder) Match(authID [16]byte) (interface{}, error) {
|
||||
for _, v := range a.aidhi {
|
||||
|
||||
t, z, r, d := v.dec.Decode(AuthID)
|
||||
t, z, r, d := v.dec.Decode(authID)
|
||||
if z != crc32.ChecksumIEEE(d[:12]) {
|
||||
continue
|
||||
}
|
||||
@ -104,18 +109,13 @@ func (a *AuthIDDecoderHolder) Match(AuthID [16]byte) (interface{}, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !a.apw.Check(AuthID[:]) {
|
||||
if !a.apw.Check(authID[:]) {
|
||||
return nil, ErrReplay
|
||||
}
|
||||
|
||||
_ = r
|
||||
|
||||
return v.ticket, nil
|
||||
|
||||
}
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
var ErrNotFound = errors.New("user do not exist")
|
||||
|
||||
var ErrReplay = errors.New("replayed request")
|
||||
|
@ -2,10 +2,11 @@ package aead
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCreateAuthID(t *testing.T) {
|
||||
@ -57,7 +58,6 @@ func TestCreateAuthIDAndDecode2(t *testing.T) {
|
||||
res2, err2 := AuthDecoder.Match(authid2)
|
||||
assert.EqualError(t, err2, "user do not exist")
|
||||
assert.Nil(t, res2)
|
||||
|
||||
}
|
||||
|
||||
func TestCreateAuthIDAndDecodeMassive(t *testing.T) {
|
||||
@ -89,7 +89,6 @@ func TestCreateAuthIDAndDecodeMassive(t *testing.T) {
|
||||
res2, err2 := AuthDecoder.Match(authid3)
|
||||
assert.Equal(t, "Demo User", res2)
|
||||
assert.Nil(t, err2)
|
||||
|
||||
}
|
||||
|
||||
func TestCreateAuthIDAndDecodeSuperMassive(t *testing.T) {
|
||||
@ -125,5 +124,4 @@ func TestCreateAuthIDAndDecodeSuperMassive(t *testing.T) {
|
||||
assert.Nil(t, err2)
|
||||
|
||||
fmt.Println(after.Sub(before).Seconds())
|
||||
|
||||
}
|
||||
|
@ -1,21 +1,14 @@
|
||||
package aead
|
||||
|
||||
const KDFSaltConst_AuthIDEncryptionKey = "AES Auth ID Encryption"
|
||||
|
||||
const KDFSaltConst_AEADRespHeaderLenKey = "AEAD Resp Header Len Key"
|
||||
|
||||
const KDFSaltConst_AEADRespHeaderLenIV = "AEAD Resp Header Len IV"
|
||||
|
||||
const KDFSaltConst_AEADRespHeaderPayloadKey = "AEAD Resp Header Key"
|
||||
|
||||
const KDFSaltConst_AEADRespHeaderPayloadIV = "AEAD Resp Header IV"
|
||||
|
||||
const KDFSaltConst_VMessAEADKDF = "VMess AEAD KDF"
|
||||
|
||||
const KDFSaltConst_VMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
|
||||
|
||||
const KDFSaltConst_VMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
|
||||
|
||||
const KDFSaltConst_VMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
|
||||
|
||||
const KDFSaltConst_VMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"
|
||||
const (
|
||||
KDFSaltConstAuthIDEncryptionKey = "AES Auth ID Encryption"
|
||||
KDFSaltConstAEADRespHeaderLenKey = "AEAD Resp Header Len Key"
|
||||
KDFSaltConstAEADRespHeaderLenIV = "AEAD Resp Header Len IV"
|
||||
KDFSaltConstAEADRespHeaderPayloadKey = "AEAD Resp Header Key"
|
||||
KDFSaltConstAEADRespHeaderPayloadIV = "AEAD Resp Header IV"
|
||||
KDFSaltConstVMessAEADKDF = "VMess AEAD KDF"
|
||||
KDFSaltConstVMessHeaderPayloadAEADKey = "VMess Header AEAD Key"
|
||||
KDFSaltConstVMessHeaderPayloadAEADIV = "VMess Header AEAD Nonce"
|
||||
KDFSaltConstVMessHeaderPayloadLengthAEADKey = "VMess Header AEAD Key_Length"
|
||||
KDFSaltConstVMessHeaderPayloadLengthAEADIV = "VMess Header AEAD Nonce_Length"
|
||||
)
|
||||
|
@ -30,9 +30,9 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
||||
var payloadHeaderLengthAEADEncrypted []byte
|
||||
|
||||
{
|
||||
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))
|
||||
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(generatedAuthID[:]), string(connectionNonce))
|
||||
|
||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
|
||||
payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||
if err != nil {
|
||||
@ -51,9 +51,9 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
||||
var payloadHeaderAEADEncrypted []byte
|
||||
|
||||
{
|
||||
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
|
||||
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(generatedAuthID[:]), string(connectionNonce))
|
||||
|
||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||
|
||||
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
|
||||
if err != nil {
|
||||
@ -71,18 +71,15 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
||||
|
||||
var outputBuffer = bytes.NewBuffer(nil)
|
||||
|
||||
common.Must2(outputBuffer.Write(generatedAuthID[:])) //16
|
||||
|
||||
common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) //2+16
|
||||
|
||||
common.Must2(outputBuffer.Write(connectionNonce)) //8
|
||||
|
||||
common.Must2(outputBuffer.Write(generatedAuthID[:])) // 16
|
||||
common.Must2(outputBuffer.Write(payloadHeaderLengthAEADEncrypted)) // 2+16
|
||||
common.Must2(outputBuffer.Write(connectionNonce)) // 8
|
||||
common.Must2(outputBuffer.Write(payloadHeaderAEADEncrypted))
|
||||
|
||||
return outputBuffer.Bytes()
|
||||
}
|
||||
|
||||
func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, error, int) {
|
||||
func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte, bool, int, error) {
|
||||
var payloadHeaderLengthAEADEncrypted [18]byte
|
||||
var nonce [8]byte
|
||||
|
||||
@ -91,23 +88,23 @@ func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte,
|
||||
authidCheckValueReadBytesCounts, err := io.ReadFull(data, payloadHeaderLengthAEADEncrypted[:])
|
||||
bytesRead += authidCheckValueReadBytesCounts
|
||||
if err != nil {
|
||||
return nil, false, err, bytesRead
|
||||
return nil, false, bytesRead, err
|
||||
}
|
||||
|
||||
nonceReadBytesCounts, err := io.ReadFull(data, nonce[:])
|
||||
bytesRead += nonceReadBytesCounts
|
||||
if err != nil {
|
||||
return nil, false, err, bytesRead
|
||||
return nil, false, bytesRead, err
|
||||
}
|
||||
|
||||
//Decrypt Length
|
||||
// Decrypt Length
|
||||
|
||||
var decryptedAEADHeaderLengthPayloadResult []byte
|
||||
|
||||
{
|
||||
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
|
||||
payloadHeaderLengthAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADKey, string(authid[:]), string(nonce[:]))
|
||||
|
||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||
|
||||
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||
if err != nil {
|
||||
@ -123,7 +120,7 @@ func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte,
|
||||
decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
|
||||
|
||||
if erropenAEAD != nil {
|
||||
return nil, true, erropenAEAD, bytesRead
|
||||
return nil, true, bytesRead, erropenAEAD
|
||||
}
|
||||
|
||||
decryptedAEADHeaderLengthPayloadResult = decryptedAEADHeaderLengthPayload
|
||||
@ -131,24 +128,24 @@ func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte,
|
||||
|
||||
var length uint16
|
||||
|
||||
common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult[:]), binary.BigEndian, &length))
|
||||
common.Must(binary.Read(bytes.NewReader(decryptedAEADHeaderLengthPayloadResult), binary.BigEndian, &length))
|
||||
|
||||
var decryptedAEADHeaderPayloadR []byte
|
||||
|
||||
var payloadHeaderAEADEncryptedReadedBytesCounts int
|
||||
|
||||
{
|
||||
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConst_VMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
|
||||
payloadHeaderAEADKey := KDF16(key[:], KDFSaltConstVMessHeaderPayloadAEADKey, string(authid[:]), string(nonce[:]))
|
||||
|
||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConst_VMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||
|
||||
//16 == AEAD Tag size
|
||||
// 16 == AEAD Tag size
|
||||
payloadHeaderAEADEncrypted := make([]byte, length+16)
|
||||
|
||||
payloadHeaderAEADEncryptedReadedBytesCounts, err = io.ReadFull(data, payloadHeaderAEADEncrypted)
|
||||
bytesRead += payloadHeaderAEADEncryptedReadedBytesCounts
|
||||
if err != nil {
|
||||
return nil, false, err, bytesRead
|
||||
return nil, false, bytesRead, err
|
||||
}
|
||||
|
||||
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
|
||||
@ -165,11 +162,11 @@ func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte,
|
||||
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
|
||||
|
||||
if erropenAEAD != nil {
|
||||
return nil, true, erropenAEAD, bytesRead
|
||||
return nil, true, bytesRead, erropenAEAD
|
||||
}
|
||||
|
||||
decryptedAEADHeaderPayloadR = decryptedAEADHeaderPayload
|
||||
}
|
||||
|
||||
return decryptedAEADHeaderPayloadR, false, nil, bytesRead
|
||||
return decryptedAEADHeaderPayloadR, false, bytesRead, nil
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func TestOpenVMessAEADHeader(t *testing.T) {
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, _, err, _ := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
out, _, _, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
|
||||
fmt.Println(string(out))
|
||||
fmt.Println(err)
|
||||
@ -41,7 +41,7 @@ func TestOpenVMessAEADHeader2(t *testing.T) {
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, _, err, readen := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
out, _, readen, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
assert.Equal(t, len(sealed)-16-AEADR.Len(), readen)
|
||||
assert.Equal(t, string(TestHeader), string(out))
|
||||
assert.Nil(t, err)
|
||||
@ -63,7 +63,7 @@ func TestOpenVMessAEADHeader4(t *testing.T) {
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, drain, err, readen := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
out, drain, readen, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
assert.Equal(t, len(sealed)-16-AEADR.Len(), readen)
|
||||
assert.Equal(t, true, drain)
|
||||
assert.NotNil(t, err)
|
||||
@ -72,12 +72,10 @@ func TestOpenVMessAEADHeader4(t *testing.T) {
|
||||
}
|
||||
assert.Nil(t, out)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestOpenVMessAEADHeader4Massive(t *testing.T) {
|
||||
for j := 0; j < 1000; j++ {
|
||||
|
||||
for i := 0; i <= 60; i++ {
|
||||
TestHeader := []byte("Test Header")
|
||||
key := KDF16([]byte("Demo Key for Auth ID Test"), "Demo Path for Auth ID Test")
|
||||
@ -93,7 +91,7 @@ func TestOpenVMessAEADHeader4Massive(t *testing.T) {
|
||||
|
||||
io.ReadFull(AEADR, authid[:])
|
||||
|
||||
out, drain, err, readen := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
out, drain, readen, err := OpenVMessAEADHeader(keyw, authid, AEADR)
|
||||
assert.Equal(t, len(sealed)-16-AEADR.Len(), readen)
|
||||
assert.Equal(t, true, drain)
|
||||
assert.NotNil(t, err)
|
||||
|
@ -7,9 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func KDF(key []byte, path ...string) []byte {
|
||||
hmacf := hmac.New(func() hash.Hash {
|
||||
return sha256.New()
|
||||
}, []byte(KDFSaltConst_VMessAEADKDF))
|
||||
hmacf := hmac.New(sha256.New, []byte(KDFSaltConstVMessAEADKDF))
|
||||
|
||||
for _, v := range path {
|
||||
hmacf = hmac.New(func() hash.Hash {
|
||||
|
@ -47,8 +47,7 @@ type ClientSession struct {
|
||||
}
|
||||
|
||||
// NewClientSession creates a new ClientSession.
|
||||
func NewClientSession(isAEAD bool, idHash protocol.IDHash, ctx context.Context) *ClientSession {
|
||||
|
||||
func NewClientSession(ctx context.Context, isAEAD bool, idHash protocol.IDHash) *ClientSession {
|
||||
session := &ClientSession{
|
||||
isAEAD: isAEAD,
|
||||
idHash: idHash,
|
||||
@ -114,7 +113,7 @@ func (c *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writ
|
||||
|
||||
if !c.isAEAD {
|
||||
iv := hashTimestamp(md5.New(), timestamp)
|
||||
aesStream := crypto.NewAesEncryptionStream(account.ID.CmdKey(), iv[:])
|
||||
aesStream := crypto.NewAesEncryptionStream(account.ID.CmdKey(), iv)
|
||||
aesStream.XORKeyStream(buffer.Bytes(), buffer.Bytes())
|
||||
common.Must2(writer.Write(buffer.Bytes()))
|
||||
} else {
|
||||
@ -193,8 +192,8 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
||||
aesStream := crypto.NewAesDecryptionStream(c.responseBodyKey[:], c.responseBodyIV[:])
|
||||
c.responseReader = crypto.NewCryptionReader(aesStream, reader)
|
||||
} else {
|
||||
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConst_AEADRespHeaderLenKey)
|
||||
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConst_AEADRespHeaderLenIV)[:12]
|
||||
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
|
||||
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
|
||||
|
||||
aeadResponseHeaderLengthEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderLengthEncryptionKey)).(cipher.Block)
|
||||
aeadResponseHeaderLengthEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||
@ -213,8 +212,8 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
||||
decryptedResponseHeaderLength = int(decryptedResponseHeaderLengthBinaryDeserializeBuffer)
|
||||
}
|
||||
|
||||
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConst_AEADRespHeaderPayloadKey)
|
||||
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConst_AEADRespHeaderPayloadIV)[:12]
|
||||
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
|
||||
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
|
||||
|
||||
aeadResponseHeaderPayloadEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey)).(cipher.Block)
|
||||
aeadResponseHeaderPayloadEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||
|
@ -43,7 +43,7 @@ func TestRequestSerialization(t *testing.T) {
|
||||
}
|
||||
|
||||
buffer := buf.New()
|
||||
client := NewClientSession(true, protocol.DefaultIDHash, context.TODO())
|
||||
client := NewClientSession(context.TODO(), true, protocol.DefaultIDHash)
|
||||
common.Must(client.EncodeRequestHeader(expectedRequest, buffer))
|
||||
|
||||
buffer2 := buf.New()
|
||||
@ -93,7 +93,7 @@ func TestInvalidRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
buffer := buf.New()
|
||||
client := NewClientSession(true, protocol.DefaultIDHash, context.TODO())
|
||||
client := NewClientSession(context.TODO(), true, protocol.DefaultIDHash)
|
||||
common.Must(client.EncodeRequestHeader(expectedRequest, buffer))
|
||||
|
||||
buffer2 := buf.New()
|
||||
@ -134,7 +134,7 @@ func TestMuxRequest(t *testing.T) {
|
||||
}
|
||||
|
||||
buffer := buf.New()
|
||||
client := NewClientSession(true, protocol.DefaultIDHash, context.TODO())
|
||||
client := NewClientSession(context.TODO(), true, protocol.DefaultIDHash)
|
||||
common.Must(client.EncodeRequestHeader(expectedRequest, buffer))
|
||||
|
||||
buffer2 := buf.New()
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
vmessaead "v2ray.com/core/proxy/vmess/aead"
|
||||
)
|
||||
|
||||
type sessionId struct {
|
||||
type sessionID struct {
|
||||
user [16]byte
|
||||
key [16]byte
|
||||
nonce [16]byte
|
||||
@ -35,14 +35,14 @@ type sessionId struct {
|
||||
// SessionHistory keeps track of historical session ids, to prevent replay attacks.
|
||||
type SessionHistory struct {
|
||||
sync.RWMutex
|
||||
cache map[sessionId]time.Time
|
||||
cache map[sessionID]time.Time
|
||||
task *task.Periodic
|
||||
}
|
||||
|
||||
// NewSessionHistory creates a new SessionHistory object.
|
||||
func NewSessionHistory() *SessionHistory {
|
||||
h := &SessionHistory{
|
||||
cache: make(map[sessionId]time.Time, 128),
|
||||
cache: make(map[sessionID]time.Time, 128),
|
||||
}
|
||||
h.task = &task.Periodic{
|
||||
Interval: time.Second * 30,
|
||||
@ -56,7 +56,7 @@ func (h *SessionHistory) Close() error {
|
||||
return h.task.Close()
|
||||
}
|
||||
|
||||
func (h *SessionHistory) addIfNotExits(session sessionId) bool {
|
||||
func (h *SessionHistory) addIfNotExits(session sessionID) bool {
|
||||
h.Lock()
|
||||
|
||||
if expire, found := h.cache[session]; found && expire.After(time.Now()) {
|
||||
@ -87,7 +87,7 @@ func (h *SessionHistory) removeExpiredEntries() error {
|
||||
}
|
||||
|
||||
if len(h.cache) == 0 {
|
||||
h.cache = make(map[sessionId]time.Time, 128)
|
||||
h.cache = make(map[sessionID]time.Time, 128)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -141,7 +141,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
readSizeRemain := DrainSize
|
||||
|
||||
drainConnection := func(e error) error {
|
||||
//We read a deterministic generated length of data before closing the connection to offset padding read pattern
|
||||
// We read a deterministic generated length of data before closing the connection to offset padding read pattern
|
||||
readSizeRemain -= int(buffer.Len())
|
||||
if readSizeRemain > 0 {
|
||||
err := s.DrainConnN(reader, readSizeRemain)
|
||||
@ -169,22 +169,24 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
var fixedSizeAuthID [16]byte
|
||||
copy(fixedSizeAuthID[:], buffer.Bytes())
|
||||
|
||||
if foundAEAD {
|
||||
switch {
|
||||
case foundAEAD:
|
||||
vmessAccount = user.Account.(*vmess.MemoryAccount)
|
||||
var fixedSizeCmdKey [16]byte
|
||||
copy(fixedSizeCmdKey[:], vmessAccount.ID.CmdKey())
|
||||
aeadData, shouldDrain, errorReason, bytesRead := vmessaead.OpenVMessAEADHeader(fixedSizeCmdKey, fixedSizeAuthID, reader)
|
||||
aeadData, shouldDrain, bytesRead, errorReason := vmessaead.OpenVMessAEADHeader(fixedSizeCmdKey, fixedSizeAuthID, reader)
|
||||
if errorReason != nil {
|
||||
if shouldDrain {
|
||||
readSizeRemain -= bytesRead
|
||||
return nil, drainConnection(newError("AEAD read failed").Base(errorReason))
|
||||
} else {
|
||||
return nil, drainConnection(newError("AEAD read failed, drain skiped").Base(errorReason))
|
||||
return nil, drainConnection(newError("AEAD read failed, drain skipped").Base(errorReason))
|
||||
}
|
||||
}
|
||||
decryptor = bytes.NewReader(aeadData)
|
||||
s.isAEADRequest = true
|
||||
} else if !s.isAEADForced && errorAEAD == vmessaead.ErrNotFound {
|
||||
|
||||
case !s.isAEADForced && errorAEAD == vmessaead.ErrNotFound:
|
||||
userLegacy, timestamp, valid, userValidationError := s.userValidator.Get(buffer.Bytes())
|
||||
if !valid || userValidationError != nil {
|
||||
return nil, drainConnection(newError("invalid user").Base(userValidationError))
|
||||
@ -193,9 +195,10 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
iv := hashTimestamp(md5.New(), timestamp)
|
||||
vmessAccount = userLegacy.Account.(*vmess.MemoryAccount)
|
||||
|
||||
aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv[:])
|
||||
aesStream := crypto.NewAesDecryptionStream(vmessAccount.ID.CmdKey(), iv)
|
||||
decryptor = crypto.NewCryptionReader(aesStream, reader)
|
||||
} else {
|
||||
|
||||
default:
|
||||
return nil, drainConnection(newError("invalid user").Base(errorAEAD))
|
||||
}
|
||||
|
||||
@ -212,7 +215,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
|
||||
copy(s.requestBodyIV[:], buffer.BytesRange(1, 17)) // 16 bytes
|
||||
copy(s.requestBodyKey[:], buffer.BytesRange(17, 33)) // 16 bytes
|
||||
var sid sessionId
|
||||
var sid sessionID
|
||||
copy(sid.user[:], vmessAccount.ID.Bytes())
|
||||
sid.key = s.requestBodyKey
|
||||
sid.nonce = s.requestBodyIV
|
||||
@ -226,7 +229,6 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
} else {
|
||||
return nil, newError("duplicated session id, possibly under replay attack, but this is a AEAD request")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s.responseHeader = buffer.Byte(33) // 1 byte
|
||||
@ -240,6 +242,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
case protocol.RequestCommandMux:
|
||||
request.Address = net.DomainAddress("v1.mux.cool")
|
||||
request.Port = 0
|
||||
|
||||
case protocol.RequestCommandTCP, protocol.RequestCommandUDP:
|
||||
if addr, port, err := addrParser.ReadAddressPort(buffer, decryptor); err == nil {
|
||||
request.Address = addr
|
||||
@ -283,12 +286,11 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request
|
||||
if burnErr != nil {
|
||||
Autherr = newError("invalid auth, can't taint legacy userHash").Base(burnErr)
|
||||
}
|
||||
//It is possible that we are under attack described in https://github.com/v2ray/v2ray-core/issues/2523
|
||||
// It is possible that we are under attack described in https://github.com/v2ray/v2ray-core/issues/2523
|
||||
return nil, drainConnection(Autherr)
|
||||
} else {
|
||||
return nil, newError("invalid auth, but this is a AEAD request")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if request.Address == nil {
|
||||
@ -327,8 +329,8 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||
}
|
||||
return crypto.NewAuthenticationReader(auth, sizeParser, reader, protocol.TransferTypePacket, padding)
|
||||
}
|
||||
|
||||
return buf.NewReader(reader)
|
||||
|
||||
case protocol.SecurityType_LEGACY:
|
||||
aesStream := crypto.NewAesDecryptionStream(s.requestBodyKey[:], s.requestBodyIV[:])
|
||||
cryptionReader := crypto.NewCryptionReader(aesStream, reader)
|
||||
@ -340,17 +342,17 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||
}
|
||||
return crypto.NewAuthenticationReader(auth, sizeParser, cryptionReader, request.Command.TransferType(), padding)
|
||||
}
|
||||
|
||||
return buf.NewReader(cryptionReader)
|
||||
|
||||
case protocol.SecurityType_AES128_GCM:
|
||||
aead := crypto.NewAesGcm(s.requestBodyKey[:])
|
||||
|
||||
auth := &crypto.AEADAuthenticator{
|
||||
AEAD: aead,
|
||||
NonceGenerator: GenerateChunkNonce(s.requestBodyIV[:], uint32(aead.NonceSize())),
|
||||
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
|
||||
}
|
||||
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding)
|
||||
|
||||
case protocol.SecurityType_CHACHA20_POLY1305:
|
||||
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.requestBodyKey[:]))
|
||||
|
||||
@ -360,6 +362,7 @@ func (s *ServerSession) DecodeRequestBody(request *protocol.RequestHeader, reade
|
||||
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
|
||||
}
|
||||
return crypto.NewAuthenticationReader(auth, sizeParser, reader, request.Command.TransferType(), padding)
|
||||
|
||||
default:
|
||||
panic("Unknown security type.")
|
||||
}
|
||||
@ -395,9 +398,8 @@ func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
|
||||
}
|
||||
|
||||
if s.isAEADRequest {
|
||||
|
||||
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConst_AEADRespHeaderLenKey)
|
||||
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConst_AEADRespHeaderLenIV)[:12]
|
||||
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
|
||||
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
|
||||
|
||||
aeadResponseHeaderLengthEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderLengthEncryptionKey)).(cipher.Block)
|
||||
aeadResponseHeaderLengthEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||
@ -411,8 +413,8 @@ func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
|
||||
AEADEncryptedLength := aeadResponseHeaderLengthEncryptionAEAD.Seal(nil, aeadResponseHeaderLengthEncryptionIV, aeadResponseHeaderLengthEncryptionBuffer.Bytes(), nil)
|
||||
common.Must2(io.Copy(writer, bytes.NewReader(AEADEncryptedLength)))
|
||||
|
||||
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConst_AEADRespHeaderPayloadKey)
|
||||
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConst_AEADRespHeaderPayloadIV)[:12]
|
||||
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
|
||||
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
|
||||
|
||||
aeadResponseHeaderPayloadEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey)).(cipher.Block)
|
||||
aeadResponseHeaderPayloadEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||
@ -447,8 +449,8 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||
}
|
||||
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, protocol.TransferTypePacket, padding)
|
||||
}
|
||||
|
||||
return buf.NewWriter(writer)
|
||||
|
||||
case protocol.SecurityType_LEGACY:
|
||||
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||
auth := &crypto.AEADAuthenticator{
|
||||
@ -458,17 +460,17 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||
}
|
||||
return crypto.NewAuthenticationWriter(auth, sizeParser, s.responseWriter, request.Command.TransferType(), padding)
|
||||
}
|
||||
|
||||
return &buf.SequentialWriter{Writer: s.responseWriter}
|
||||
|
||||
case protocol.SecurityType_AES128_GCM:
|
||||
aead := crypto.NewAesGcm(s.responseBodyKey[:])
|
||||
|
||||
auth := &crypto.AEADAuthenticator{
|
||||
AEAD: aead,
|
||||
NonceGenerator: GenerateChunkNonce(s.responseBodyIV[:], uint32(aead.NonceSize())),
|
||||
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
|
||||
}
|
||||
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding)
|
||||
|
||||
case protocol.SecurityType_CHACHA20_POLY1305:
|
||||
aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(s.responseBodyKey[:]))
|
||||
|
||||
@ -478,6 +480,7 @@ func (s *ServerSession) EncodeResponseBody(request *protocol.RequestHeader, writ
|
||||
AdditionalDataGenerator: crypto.GenerateEmptyBytes(),
|
||||
}
|
||||
return crypto.NewAuthenticationWriter(auth, sizeParser, writer, request.Command.TransferType(), padding)
|
||||
|
||||
default:
|
||||
panic("Unknown security type.")
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
if err != nil {
|
||||
return newError("failed to find an available destination").Base(err).AtWarning()
|
||||
}
|
||||
defer conn.Close() //nolint: errcheck
|
||||
defer conn.Close()
|
||||
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
@ -114,11 +114,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
output := link.Writer
|
||||
|
||||
isAEAD := false
|
||||
if !aead_disabled && len(account.AlterIDs) == 0 {
|
||||
if !aeadDisabled && len(account.AlterIDs) == 0 {
|
||||
isAEAD = true
|
||||
}
|
||||
|
||||
session := encoding.NewClientSession(isAEAD, protocol.DefaultIDHash, ctx)
|
||||
session := encoding.NewClientSession(ctx, isAEAD, protocol.DefaultIDHash)
|
||||
sessionPolicy := h.policyManager.ForLevel(request.User.Level)
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
@ -179,7 +179,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
var (
|
||||
enablePadding = false
|
||||
aead_disabled = false
|
||||
aeadDisabled = false
|
||||
)
|
||||
|
||||
func shouldEnablePadding(s protocol.SecurityType) bool {
|
||||
@ -198,8 +198,8 @@ func init() {
|
||||
enablePadding = true
|
||||
}
|
||||
|
||||
aeadDisabled := platform.NewEnvFlag("v2ray.vmess.aead.disabled").GetValue(func() string { return defaultFlagValue })
|
||||
if aeadDisabled == "true" {
|
||||
aead_disabled = true
|
||||
isAeadDisabled := platform.NewEnvFlag("v2ray.vmess.aead.disabled").GetValue(func() string { return defaultFlagValue })
|
||||
if isAeadDisabled == "true" {
|
||||
aeadDisabled = true
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ package vmess
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"hash"
|
||||
"hash/crc64"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -142,7 +141,7 @@ func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error {
|
||||
|
||||
account := uu.user.Account.(*MemoryAccount)
|
||||
if !v.behaviorFused {
|
||||
hashkdf := hmac.New(func() hash.Hash { return sha256.New() }, []byte("VMESSBSKDF"))
|
||||
hashkdf := hmac.New(sha256.New, []byte("VMESSBSKDF"))
|
||||
hashkdf.Write(account.ID.Bytes())
|
||||
v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil))
|
||||
}
|
||||
|
@ -3,13 +3,13 @@ package scenarios
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"v2ray.com/core"
|
||||
|
@ -203,6 +203,5 @@ func testTCPConn2(conn net.Conn, payloadSize int, timeout time.Duration) func()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package scenarios
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -136,7 +137,7 @@ func TestHttpError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpConnectMethod(t *testing.T) {
|
||||
func TestHTTPConnectMethod(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
@ -179,7 +180,9 @@ func TestHttpConnectMethod(t *testing.T) {
|
||||
|
||||
payload := make([]byte, 1024*64)
|
||||
common.Must2(rand.Read(payload))
|
||||
req, err := http.NewRequest("Connect", "http://"+dest.NetAddr()+"/", bytes.NewReader(payload))
|
||||
|
||||
ctx := context.Background()
|
||||
req, err := http.NewRequestWithContext(ctx, "Connect", "http://"+dest.NetAddr()+"/", bytes.NewReader(payload))
|
||||
req.Header.Set("X-a", "b")
|
||||
req.Header.Set("X-b", "d")
|
||||
common.Must(err)
|
||||
@ -334,7 +337,8 @@ func TestHttpBasicAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
req, err := http.NewRequest("GET", "http://127.0.0.1:"+httpServerPort.String(), nil)
|
||||
ctx := context.Background()
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "http://127.0.0.1:"+httpServerPort.String(), nil)
|
||||
common.Must(err)
|
||||
|
||||
setProxyBasicAuth(req, "a", "c")
|
||||
@ -346,7 +350,8 @@ func TestHttpBasicAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
req, err := http.NewRequest("GET", "http://127.0.0.1:"+httpServerPort.String(), nil)
|
||||
ctx := context.Background()
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "http://127.0.0.1:"+httpServerPort.String(), nil)
|
||||
common.Must(err)
|
||||
|
||||
setProxyBasicAuth(req, "a", "b")
|
||||
|
@ -226,7 +226,7 @@ func TestShadowsocksAES128UDP(t *testing.T) {
|
||||
payload := make([]byte, 1024)
|
||||
common.Must2(rand.Read(payload))
|
||||
|
||||
nBytes, err := conn.Write([]byte(payload))
|
||||
nBytes, err := conn.Write(payload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import (
|
||||
tcptransport "v2ray.com/core/transport/internet/tcp"
|
||||
)
|
||||
|
||||
func TestHttpConnectionHeader(t *testing.T) {
|
||||
func TestHTTPConnectionHeader(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ func (s *Server) Start() (net.Destination, error) {
|
||||
Handler: s,
|
||||
}
|
||||
go s.server.ListenAndServe()
|
||||
return net.TCPDestination(net.LocalHostIP, net.Port(s.Port)), nil
|
||||
return net.TCPDestination(net.LocalHostIP, s.Port), nil
|
||||
}
|
||||
|
||||
func (s *Server) Close() error {
|
||||
|
@ -65,7 +65,7 @@ func (server *Server) handleConnection(conn net.Conn) {
|
||||
|
||||
pReader, pWriter := pipe.New(pipe.WithoutSizeLimit())
|
||||
err := task.Run(context.Background(), func() error {
|
||||
defer pWriter.Close() // nolint: errcheck
|
||||
defer pWriter.Close()
|
||||
|
||||
for {
|
||||
b := buf.New()
|
||||
@ -102,7 +102,7 @@ func (server *Server) handleConnection(conn net.Conn) {
|
||||
fmt.Println("failed to transfer data: ", err.Error())
|
||||
}
|
||||
|
||||
conn.Close() // nolint: errcheck
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
func (server *Server) Close() error {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user