|
|
|
@ -271,6 +271,67 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|
|
|
|
return inbound, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DispatchLink implements routing.Dispatcher.
|
|
|
|
|
func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.Destination, outbound *transport.Link) error { |
|
|
|
|
if !destination.IsValid() { |
|
|
|
|
return newError("Dispatcher: Invalid destination.") |
|
|
|
|
} |
|
|
|
|
ob := &session.Outbound{ |
|
|
|
|
Target: destination, |
|
|
|
|
} |
|
|
|
|
ctx = session.ContextWithOutbound(ctx, ob) |
|
|
|
|
content := session.ContentFromContext(ctx) |
|
|
|
|
if content == nil { |
|
|
|
|
content = new(session.Content) |
|
|
|
|
ctx = session.ContextWithContent(ctx, content) |
|
|
|
|
} |
|
|
|
|
sniffingRequest := content.SniffingRequest |
|
|
|
|
switch { |
|
|
|
|
case !sniffingRequest.Enabled: |
|
|
|
|
go d.routedDispatch(ctx, outbound, destination) |
|
|
|
|
case destination.Network != net.Network_TCP: |
|
|
|
|
// Only metadata sniff will be used for non tcp connection
|
|
|
|
|
result, err := sniffer(ctx, nil, true) |
|
|
|
|
if err == nil { |
|
|
|
|
content.Protocol = result.Protocol() |
|
|
|
|
if shouldOverride(result, sniffingRequest.OverrideDestinationForProtocol) { |
|
|
|
|
domain := result.Domain() |
|
|
|
|
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx)) |
|
|
|
|
destination.Address = net.ParseAddress(domain) |
|
|
|
|
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" { |
|
|
|
|
ob.RouteTarget = destination |
|
|
|
|
} else { |
|
|
|
|
ob.Target = destination |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
go d.routedDispatch(ctx, outbound, destination) |
|
|
|
|
default: |
|
|
|
|
go func() { |
|
|
|
|
cReader := &cachedReader{ |
|
|
|
|
reader: outbound.Reader.(*pipe.Reader), |
|
|
|
|
} |
|
|
|
|
outbound.Reader = cReader |
|
|
|
|
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly) |
|
|
|
|
if err == nil { |
|
|
|
|
content.Protocol = result.Protocol() |
|
|
|
|
} |
|
|
|
|
if err == nil && shouldOverride(result, sniffingRequest.OverrideDestinationForProtocol) { |
|
|
|
|
domain := result.Domain() |
|
|
|
|
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx)) |
|
|
|
|
destination.Address = net.ParseAddress(domain) |
|
|
|
|
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" { |
|
|
|
|
ob.RouteTarget = destination |
|
|
|
|
} else { |
|
|
|
|
ob.Target = destination |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
d.routedDispatch(ctx, outbound, destination) |
|
|
|
|
}() |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (SniffResult, error) { |
|
|
|
|
payload := buf.New() |
|
|
|
|
defer payload.Release() |
|
|
|
|