Skip to content

Commit

Permalink
Update v2ray to 4.23.1
Browse files Browse the repository at this point in the history
  • Loading branch information
emc2314 committed May 31, 2020
2 parents 3a44812 + ea62c93 commit 1f208ac
Show file tree
Hide file tree
Showing 49 changed files with 4,750 additions and 992 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.DS_Store
bazel-*
.idea
17 changes: 10 additions & 7 deletions app/dispatcher/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,13 @@ func sniffer(ctx context.Context, cReader *cachedReader) (SniffResult, error) {

func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
var handler outbound.Handler
if d.router != nil {

skipRoutePick := false
if content := session.ContentFromContext(ctx); content != nil {
skipRoutePick = content.SkipRoutePick
}

if d.router != nil && !skipRoutePick {
if tag, err := d.router.PickRoute(ctx); err == nil {
if h := d.ohm.GetHandler(tag); h != nil {
newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
Expand All @@ -282,12 +288,9 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
return
}

accessMessage := log.AccessMessageFromContext(ctx)
if accessMessage != nil {
if len(handler.Tag()) > 0 {
accessMessage.Detour = handler.Tag()
} else {
accessMessage.Detour = ""
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
if tag := handler.Tag(); tag != "" {
accessMessage.Detour = tag
}
log.Record(accessMessage)
}
Expand Down
159 changes: 89 additions & 70 deletions app/dns/dohdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,32 @@ import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"sync"
"sync/atomic"
"time"

dns_feature "v2ray.com/core/features/dns"

"golang.org/x/net/dns/dnsmessage"
"v2ray.com/core/common"
"v2ray.com/core/common/dice"
"v2ray.com/core/common/net"
"v2ray.com/core/common/protocol/dns"
"v2ray.com/core/common/session"
"v2ray.com/core/common/signal/pubsub"
"v2ray.com/core/common/task"
"v2ray.com/core/features/routing"
"v2ray.com/core/transport/internet"
)

// DoHNameServer implimented DNS over HTTPS (RFC8484) Wire Format,
// which is compatiable with traditional dns over udp(RFC1035),
// thus most of the DOH implimentation is copied from udpns.go
type DoHNameServer struct {
sync.RWMutex
dispatcher routing.Dispatcher
dohDests []net.Destination
ips map[string]record
pub *pubsub.Service
cleanup *task.Periodic
Expand All @@ -44,41 +45,8 @@ type DoHNameServer struct {
// NewDoHNameServer creates DOH client object for remote resolving
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.IP) (*DoHNameServer, error) {

dohAddr := net.ParseAddress(url.Hostname())
dohPort := "443"
if url.Port() != "" {
dohPort = url.Port()
}

parseIPDest := func(ip net.IP, port string) net.Destination {
strIP := ip.String()
if len(ip) == net.IPv6len {
strIP = fmt.Sprintf("[%s]", strIP)
}
dest, err := net.ParseDestination(fmt.Sprintf("tcp:%s:%s", strIP, port))
common.Must(err)
return dest
}

var dests []net.Destination
if dohAddr.Family().IsDomain() {
// resolve DOH server in advance
ips, err := net.LookupIP(dohAddr.Domain())
if err != nil || len(ips) == 0 {
return nil, err
}
for _, ip := range ips {
dests = append(dests, parseIPDest(ip, dohPort))
}
} else {
ip := dohAddr.IP()
dests = append(dests, parseIPDest(ip, dohPort))
}

newError("DNS: created Remote DOH client for ", url.String(), ", preresolved Dests: ", dests).AtInfo().WriteToLog()
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog()
s := baseDOHNameServer(url, "DOH", clientIP)
s.dispatcher = dispatcher
s.dohDests = dests

// Dispatched connection will be closed (interupted) after each request
// This makes DOH inefficient without a keeped-alive connection
Expand All @@ -87,15 +55,29 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.
// Recommand to use NewDoHLocalNameServer (DOHL:) if v2ray instance is running on
// a normal network eg. the server side of v2ray
tr := &http.Transport{
MaxIdleConns: 10,
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
DialContext: s.DialContext,
TLSHandshakeTimeout: 30 * time.Second,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}

link, err := dispatcher.Dispatch(ctx, dest)
if err != nil {
return nil, err
}
return net.NewConnection(
net.ConnectionInputMulti(link.Writer),
net.ConnectionOutputMulti(link.Reader),
), nil
},
}

dispatchedClient := &http.Client{
Transport: tr,
Timeout: 16 * time.Second,
Timeout: 60 * time.Second,
}

s.httpClient = dispatchedClient
Expand All @@ -106,8 +88,23 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.
func NewDoHLocalNameServer(url *url.URL, clientIP net.IP) *DoHNameServer {
url.Scheme = "https"
s := baseDOHNameServer(url, "DOHL", clientIP)
tr := &http.Transport{
IdleConnTimeout: 90 * time.Second,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
conn, err := internet.DialSystem(ctx, dest, nil)
if err != nil {
return nil, err
}
return conn, nil
},
}
s.httpClient = &http.Client{
Timeout: time.Second * 180,
Timeout: time.Second * 180,
Transport: tr,
}
newError("DNS: created Local DOH client for ", url.String()).AtInfo().WriteToLog()
return s
Expand All @@ -119,7 +116,7 @@ func baseDOHNameServer(url *url.URL, prefix string, clientIP net.IP) *DoHNameSer
ips: make(map[string]record),
clientIP: clientIP,
pub: pubsub.NewService(),
name: fmt.Sprintf("%s//%s", prefix, url.Host),
name: prefix + "//" + url.Host,
dohURL: url.String(),
}
s.cleanup = &task.Periodic{
Expand All @@ -135,21 +132,6 @@ func (s *DoHNameServer) Name() string {
return s.name
}

// DialContext offer dispatched connection through core routing
func (s *DoHNameServer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {

dest := s.dohDests[dice.Roll(len(s.dohDests))]

link, err := s.dispatcher.Dispatch(ctx, dest)
if err != nil {
return nil, err
}
return net.NewConnection(
net.ConnectionInputMulti(link.Writer),
net.ConnectionOutputMulti(link.Reader),
), nil
}

// Cleanup clears expired items from cache
func (s *DoHNameServer) Cleanup() error {
now := time.Now()
Expand Down Expand Up @@ -185,7 +167,6 @@ func (s *DoHNameServer) Cleanup() error {

func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
elapsed := time.Since(req.start)
newError(s.name, " got answere: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog()

s.Lock()
rec := s.ips[req.domain]
Expand All @@ -198,17 +179,29 @@ func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
updated = true
}
case dnsmessage.TypeAAAA:
addr := make([]net.Address, 0)
for _, ip := range ipRec.IP {
if len(ip.IP()) == net.IPv6len {
addr = append(addr, ip)
}
}
ipRec.IP = addr
if isNewer(rec.AAAA, ipRec) {
rec.AAAA = ipRec
updated = true
}
}
newError(s.name, " got answere: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog()

if updated {
s.ips[req.domain] = rec
s.pub.Publish(req.domain, nil)
}

switch req.reqType {
case dnsmessage.TypeA:
s.pub.Publish(req.domain+"4", nil)
case dnsmessage.TypeAAAA:
s.pub.Publish(req.domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
}
Expand Down Expand Up @@ -243,7 +236,8 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, option IPO
}

dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
Protocol: "https",
Protocol: "https",
SkipRoutePick: true,
})

// forced to use mux for DOH
Expand Down Expand Up @@ -285,10 +279,9 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
}

defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("DOH HTTPS server returned with non-OK code %d", resp.StatusCode)
return nil, err
io.Copy(ioutil.Discard, resp.Body) // flush resp.Body so that the conn is reusable
return nil, fmt.Errorf("DOH server returned code %d", resp.StatusCode)
}

return ioutil.ReadAll(resp.Body)
Expand Down Expand Up @@ -329,12 +322,15 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option IPOption) ([]net.
return nil, lastErr
}

if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
return nil, dns_feature.ErrEmptyResponse
}

return nil, errRecordNotFound
}

// QueryIP is called from dns.Server->queryIPTimeout
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option IPOption) ([]net.IP, error) {

fqdn := Fqdn(domain)

ips, err := s.findIPsForDomain(fqdn, option)
Expand All @@ -343,9 +339,32 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option IPOpt
return ips, err
}

sub := s.pub.Subscribe(fqdn)
defer sub.Close()

// ipv4 and ipv6 belong to different subscription groups
var sub4, sub6 *pubsub.Subscriber
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, option)

for {
Expand All @@ -357,7 +376,7 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option IPOpt
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-sub.Wait():
case <-done:
}
}
}
39 changes: 33 additions & 6 deletions app/dns/udpns.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,13 @@ func (s *ClassicNameServer) updateIP(domain string, newRec record) {

if updated {
s.ips[domain] = rec
s.pub.Publish(domain, nil)
}

if newRec.A != nil {
s.pub.Publish(domain+"4", nil)
}
if newRec.AAAA != nil {
s.pub.Publish(domain+"6", nil)
}
s.Unlock()
common.Must(s.cleanup.Start())
}
Expand Down Expand Up @@ -245,9 +249,32 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option I
return ips, err
}

sub := s.pub.Subscribe(fqdn)
defer sub.Close()

// ipv4 and ipv6 belong to different subscription groups
var sub4, sub6 *pubsub.Subscriber
if option.IPv4Enable {
sub4 = s.pub.Subscribe(fqdn + "4")
defer sub4.Close()
}
if option.IPv6Enable {
sub6 = s.pub.Subscribe(fqdn + "6")
defer sub6.Close()
}
done := make(chan interface{})
go func() {
if sub4 != nil {
select {
case <-sub4.Wait():
case <-ctx.Done():
}
}
if sub6 != nil {
select {
case <-sub6.Wait():
case <-ctx.Done():
}
}
close(done)
}()
s.sendQuery(ctx, fqdn, option)

for {
Expand All @@ -259,7 +286,7 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option I
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-sub.Wait():
case <-done:
}
}
}
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- template: azure-pipelines.template.yml
parameters:
name: macos
vmImage: 'macOS-10.13'
vmImage: 'macOS-10.14'

- job: linux_coverage
dependsOn: linux
Expand Down
Loading

0 comments on commit 1f208ac

Please sign in to comment.