mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-30 05:56:54 -05:00
Refine unix domain socket (#367)
This commit is contained in:
parent
f17063a08a
commit
770b994337
@ -87,17 +87,14 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
}
|
}
|
||||||
mss.SocketSettings.ReceiveOriginalDestAddress = true
|
mss.SocketSettings.ReceiveOriginalDestAddress = true
|
||||||
}
|
}
|
||||||
|
if pr == nil {
|
||||||
|
if net.HasNetwork(nl, net.Network_UNIX) {
|
||||||
|
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
|
||||||
|
|
||||||
for port := pr.From; port <= pr.To; port++ {
|
worker := &dsWorker{
|
||||||
if net.HasNetwork(nl, net.Network_TCP) {
|
|
||||||
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
|
||||||
|
|
||||||
worker := &tcpWorker{
|
|
||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
|
||||||
proxy: p,
|
proxy: p,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
||||||
@ -107,19 +104,41 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if pr != nil {
|
||||||
|
for port := pr.From; port <= pr.To; port++ {
|
||||||
|
if net.HasNetwork(nl, net.Network_TCP) {
|
||||||
|
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
||||||
|
|
||||||
if net.HasNetwork(nl, net.Network_UDP) {
|
worker := &tcpWorker{
|
||||||
worker := &udpWorker{
|
address: address,
|
||||||
tag: tag,
|
port: net.Port(port),
|
||||||
proxy: p,
|
proxy: p,
|
||||||
address: address,
|
stream: mss,
|
||||||
port: net.Port(port),
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
dispatcher: h.mux,
|
tag: tag,
|
||||||
uplinkCounter: uplinkCounter,
|
dispatcher: h.mux,
|
||||||
downlinkCounter: downlinkCounter,
|
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
||||||
stream: mss,
|
uplinkCounter: uplinkCounter,
|
||||||
|
downlinkCounter: downlinkCounter,
|
||||||
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
h.workers = append(h.workers, worker)
|
||||||
|
}
|
||||||
|
|
||||||
|
if net.HasNetwork(nl, net.Network_UDP) {
|
||||||
|
worker := &udpWorker{
|
||||||
|
tag: tag,
|
||||||
|
proxy: p,
|
||||||
|
address: address,
|
||||||
|
port: net.Port(port),
|
||||||
|
dispatcher: h.mux,
|
||||||
|
uplinkCounter: uplinkCounter,
|
||||||
|
downlinkCounter: downlinkCounter,
|
||||||
|
stream: mss,
|
||||||
|
}
|
||||||
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,3 +398,86 @@ func (w *udpWorker) Port() net.Port {
|
|||||||
func (w *udpWorker) Proxy() proxy.Inbound {
|
func (w *udpWorker) Proxy() proxy.Inbound {
|
||||||
return w.proxy
|
return w.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type dsWorker struct {
|
||||||
|
address net.Address
|
||||||
|
proxy proxy.Inbound
|
||||||
|
stream *internet.MemoryStreamConfig
|
||||||
|
tag string
|
||||||
|
dispatcher routing.Dispatcher
|
||||||
|
sniffingConfig *proxyman.SniffingConfig
|
||||||
|
uplinkCounter stats.Counter
|
||||||
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
|
hub internet.Listener
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *dsWorker) callback(conn internet.Connection) {
|
||||||
|
ctx, cancel := context.WithCancel(w.ctx)
|
||||||
|
sid := session.NewID()
|
||||||
|
ctx = session.ContextWithID(ctx, sid)
|
||||||
|
|
||||||
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
|
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||||
|
Gateway: net.UnixDestination(w.address),
|
||||||
|
Tag: w.tag,
|
||||||
|
})
|
||||||
|
content := new(session.Content)
|
||||||
|
if w.sniffingConfig != nil {
|
||||||
|
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||||
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
|
}
|
||||||
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
||||||
|
conn = &internet.StatCouterConnection{
|
||||||
|
Connection: conn,
|
||||||
|
ReadCounter: w.uplinkCounter,
|
||||||
|
WriteCounter: w.downlinkCounter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
|
||||||
|
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
if err := conn.Close(); err != nil {
|
||||||
|
newError("failed to close connection").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *dsWorker) Proxy() proxy.Inbound {
|
||||||
|
return w.proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *dsWorker) Port() net.Port {
|
||||||
|
return net.Port(0)
|
||||||
|
}
|
||||||
|
func (w *dsWorker) Start() error {
|
||||||
|
ctx := context.Background()
|
||||||
|
hub, err := internet.ListenUnix(ctx, w.address, w.stream, func(conn internet.Connection) {
|
||||||
|
go w.callback(conn)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return newError("failed to listen Unix Domain Socket on ", w.address).AtWarning().Base(err)
|
||||||
|
}
|
||||||
|
w.hub = hub
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *dsWorker) Close() error {
|
||||||
|
var errors []interface{}
|
||||||
|
if w.hub != nil {
|
||||||
|
if err := common.Close(w.hub); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
if err := common.Close(w.proxy); err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(errors) > 0 {
|
||||||
|
return newError("failed to close all resources").Base(newError(serial.Concat(errors...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -20,8 +20,7 @@ func DestinationFromAddr(addr net.Addr) Destination {
|
|||||||
case *net.UDPAddr:
|
case *net.UDPAddr:
|
||||||
return UDPDestination(IPAddress(addr.IP), Port(addr.Port))
|
return UDPDestination(IPAddress(addr.IP), Port(addr.Port))
|
||||||
case *net.UnixAddr:
|
case *net.UnixAddr:
|
||||||
// TODO: deal with Unix domain socket
|
return UnixDestination(DomainAddress(addr.Name))
|
||||||
return TCPDestination(LocalHostIP, Port(9))
|
|
||||||
default:
|
default:
|
||||||
panic("Net: Unknown address type.")
|
panic("Net: Unknown address type.")
|
||||||
}
|
}
|
||||||
@ -39,6 +38,9 @@ func ParseDestination(dest string) (Destination, error) {
|
|||||||
} else if strings.HasPrefix(dest, "udp:") {
|
} else if strings.HasPrefix(dest, "udp:") {
|
||||||
d.Network = Network_UDP
|
d.Network = Network_UDP
|
||||||
dest = dest[4:]
|
dest = dest[4:]
|
||||||
|
} else if strings.HasPrefix(dest, "unix:") {
|
||||||
|
d = UnixDestination(DomainAddress(dest[5:]))
|
||||||
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
hstr, pstr, err := SplitHostPort(dest)
|
hstr, pstr, err := SplitHostPort(dest)
|
||||||
@ -76,9 +78,23 @@ func UDPDestination(address Address, port Port) Destination {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnixDestination creates a Unix destination with given address
|
||||||
|
func UnixDestination(address Address) Destination {
|
||||||
|
return Destination{
|
||||||
|
Network: Network_UNIX,
|
||||||
|
Address: address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NetAddr returns the network address in this Destination in string form.
|
// NetAddr returns the network address in this Destination in string form.
|
||||||
func (d Destination) NetAddr() string {
|
func (d Destination) NetAddr() string {
|
||||||
return d.Address.String() + ":" + d.Port.String()
|
addr := ""
|
||||||
|
if d.Network == Network_TCP || d.Network == Network_UDP {
|
||||||
|
addr = d.Address.String() + ":" + d.Port.String()
|
||||||
|
} else if d.Network == Network_UNIX {
|
||||||
|
addr = d.Address.String()
|
||||||
|
}
|
||||||
|
return addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the strings form of this Destination.
|
// String returns the strings form of this Destination.
|
||||||
@ -89,6 +105,8 @@ func (d Destination) String() string {
|
|||||||
prefix = "tcp:"
|
prefix = "tcp:"
|
||||||
case Network_UDP:
|
case Network_UDP:
|
||||||
prefix = "udp:"
|
prefix = "udp:"
|
||||||
|
case Network_UNIX:
|
||||||
|
prefix = "unix:"
|
||||||
}
|
}
|
||||||
return prefix + d.NetAddr()
|
return prefix + d.NetAddr()
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,12 @@ func TestDestinationProperty(t *testing.T) {
|
|||||||
String: "udp:[2001:4860:4860::8888]:53",
|
String: "udp:[2001:4860:4860::8888]:53",
|
||||||
NetString: "[2001:4860:4860::8888]:53",
|
NetString: "[2001:4860:4860::8888]:53",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Input: UnixDestination(DomainAddress("/tmp/test.sock")),
|
||||||
|
Network: Network_UNIX,
|
||||||
|
String: "unix:/tmp/test.sock",
|
||||||
|
NetString: "/tmp/test.sock",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
@ -57,6 +63,10 @@ func TestDestinationParse(t *testing.T) {
|
|||||||
Input: "udp:8.8.8.8:53",
|
Input: "udp:8.8.8.8:53",
|
||||||
Output: UDPDestination(IPAddress([]byte{8, 8, 8, 8}), Port(53)),
|
Output: UDPDestination(IPAddress([]byte{8, 8, 8, 8}), Port(53)),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Input: "unix:/tmp/test.sock",
|
||||||
|
Output: UnixDestination(DomainAddress("/tmp/test.sock")),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Input: "8.8.8.8:53",
|
Input: "8.8.8.8:53",
|
||||||
Output: Destination{
|
Output: Destination{
|
||||||
@ -79,6 +89,10 @@ func TestDestinationParse(t *testing.T) {
|
|||||||
Input: "8.8.8.8:http",
|
Input: "8.8.8.8:http",
|
||||||
Error: true,
|
Error: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Input: "/tmp/test.sock",
|
||||||
|
Error: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testcase := range cases {
|
for _, testcase := range cases {
|
||||||
|
@ -6,6 +6,8 @@ func (n Network) SystemString() string {
|
|||||||
return "tcp"
|
return "tcp"
|
||||||
case Network_UDP:
|
case Network_UDP:
|
||||||
return "udp"
|
return "udp"
|
||||||
|
case Network_UNIX:
|
||||||
|
return "unix"
|
||||||
default:
|
default:
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ const (
|
|||||||
Network_RawTCP Network = 1
|
Network_RawTCP Network = 1
|
||||||
Network_TCP Network = 2
|
Network_TCP Network = 2
|
||||||
Network_UDP Network = 3
|
Network_UDP Network = 3
|
||||||
|
Network_UNIX Network = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for Network.
|
// Enum value maps for Network.
|
||||||
@ -42,12 +43,14 @@ var (
|
|||||||
1: "RawTCP",
|
1: "RawTCP",
|
||||||
2: "TCP",
|
2: "TCP",
|
||||||
3: "UDP",
|
3: "UDP",
|
||||||
|
4: "UNIX",
|
||||||
}
|
}
|
||||||
Network_value = map[string]int32{
|
Network_value = map[string]int32{
|
||||||
"Unknown": 0,
|
"Unknown": 0,
|
||||||
"RawTCP": 1,
|
"RawTCP": 1,
|
||||||
"TCP": 2,
|
"TCP": 2,
|
||||||
"UDP": 3,
|
"UDP": 3,
|
||||||
|
"UNIX": 4,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -136,16 +139,17 @@ var file_common_net_network_proto_rawDesc = []byte{
|
|||||||
0x12, 0x38, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x03, 0x28,
|
0x12, 0x38, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||||
0x0e, 0x32, 0x1e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63,
|
0x0e, 0x32, 0x1e, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63,
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
||||||
0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2a, 0x38, 0x0a, 0x07, 0x4e, 0x65,
|
0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2a, 0x42, 0x0a, 0x07, 0x4e, 0x65,
|
||||||
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e,
|
0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e,
|
||||||
0x10, 0x00, 0x12, 0x0e, 0x0a, 0x06, 0x52, 0x61, 0x77, 0x54, 0x43, 0x50, 0x10, 0x01, 0x1a, 0x02,
|
0x10, 0x00, 0x12, 0x0e, 0x0a, 0x06, 0x52, 0x61, 0x77, 0x54, 0x43, 0x50, 0x10, 0x01, 0x1a, 0x02,
|
||||||
0x08, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x55,
|
0x08, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x55,
|
||||||
0x44, 0x50, 0x10, 0x03, 0x42, 0x50, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61,
|
0x44, 0x50, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x4e, 0x49, 0x58, 0x10, 0x04, 0x42, 0x50,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65,
|
||||||
0x74, 0x50, 0x01, 0x5a, 0x19, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x19, 0x76,
|
||||||
0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0xaa, 0x02,
|
0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f,
|
||||||
0x15, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x15, 0x56, 0x32, 0x52, 0x61, 0x79,
|
||||||
0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4e, 0x65, 0x74,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -12,9 +12,8 @@ enum Network {
|
|||||||
RawTCP = 1 [deprecated = true];
|
RawTCP = 1 [deprecated = true];
|
||||||
TCP = 2;
|
TCP = 2;
|
||||||
UDP = 3;
|
UDP = 3;
|
||||||
|
UNIX = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkList is a list of Networks.
|
// NetworkList is a list of Networks.
|
||||||
message NetworkList {
|
message NetworkList { repeated Network network = 1; }
|
||||||
repeated Network network = 1;
|
|
||||||
}
|
|
||||||
|
@ -62,6 +62,8 @@ func (v Network) Build() net.Network {
|
|||||||
return net.Network_TCP
|
return net.Network_TCP
|
||||||
case "udp":
|
case "udp":
|
||||||
return net.Network_UDP
|
return net.Network_UDP
|
||||||
|
case "unix":
|
||||||
|
return net.Network_UNIX
|
||||||
default:
|
default:
|
||||||
return net.Network_Unknown
|
return net.Network_Unknown
|
||||||
}
|
}
|
||||||
|
@ -222,19 +222,17 @@ func (c *QUICConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DomainSocketConfig struct {
|
type DomainSocketConfig struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Abstract bool `json:"abstract"`
|
Abstract bool `json:"abstract"`
|
||||||
Padding bool `json:"padding"`
|
Padding bool `json:"padding"`
|
||||||
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *DomainSocketConfig) Build() (proto.Message, error) {
|
func (c *DomainSocketConfig) Build() (proto.Message, error) {
|
||||||
return &domainsocket.Config{
|
return &domainsocket.Config{
|
||||||
Path: c.Path,
|
Path: c.Path,
|
||||||
Abstract: c.Abstract,
|
Abstract: c.Abstract,
|
||||||
Padding: c.Padding,
|
Padding: c.Padding,
|
||||||
AcceptProxyProtocol: c.AcceptProxyProtocol,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,9 +419,10 @@ func (p TransportProtocol) Build() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SocketConfig struct {
|
type SocketConfig struct {
|
||||||
Mark int32 `json:"mark"`
|
Mark int32 `json:"mark"`
|
||||||
TFO *bool `json:"tcpFastOpen"`
|
TFO *bool `json:"tcpFastOpen"`
|
||||||
TProxy string `json:"tproxy"`
|
TProxy string `json:"tproxy"`
|
||||||
|
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
@ -447,9 +446,10 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &internet.SocketConfig{
|
return &internet.SocketConfig{
|
||||||
Mark: c.Mark,
|
Mark: c.Mark,
|
||||||
Tfo: tfoSettings,
|
Tfo: tfoSettings,
|
||||||
Tproxy: tproxy,
|
Tproxy: tproxy,
|
||||||
|
AcceptProxyProtocol: c.AcceptProxyProtocol,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
|
|||||||
case '@', '/':
|
case '@', '/':
|
||||||
fb.Type = "unix"
|
fb.Type = "unix"
|
||||||
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && runtime.GOOS == "linux" {
|
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && runtime.GOOS == "linux" {
|
||||||
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work in front of haproxy
|
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
|
||||||
copy(fullAddr, fb.Dest[1:])
|
copy(fullAddr, fb.Dest[1:])
|
||||||
fb.Dest = string(fullAddr)
|
fb.Dest = string(fullAddr)
|
||||||
}
|
}
|
||||||
|
@ -156,17 +156,34 @@ type InboundDetourConfig struct {
|
|||||||
func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
||||||
receiverSettings := &proxyman.ReceiverConfig{}
|
receiverSettings := &proxyman.ReceiverConfig{}
|
||||||
|
|
||||||
if c.PortRange == nil {
|
if c.ListenOn == nil {
|
||||||
return nil, newError("port range not specified in InboundDetour.")
|
// Listen on anyip, must set PortRange
|
||||||
}
|
if c.PortRange == nil {
|
||||||
receiverSettings.PortRange = c.PortRange.Build()
|
return nil, newError("Listen on AnyIP but no Port(s) set in InboundDetour.")
|
||||||
|
}
|
||||||
if c.ListenOn != nil {
|
receiverSettings.PortRange = c.PortRange.Build()
|
||||||
if c.ListenOn.Family().IsDomain() {
|
} else {
|
||||||
|
// Listen on specific IP or Unix Domain Socket
|
||||||
|
receiverSettings.Listen = c.ListenOn.Build()
|
||||||
|
listenDS := c.ListenOn.Family().IsDomain() && (c.ListenOn.Domain()[0] == '/' || c.ListenOn.Domain()[0] == '@')
|
||||||
|
listenIP := c.ListenOn.Family().IsIP() || (c.ListenOn.Family().IsDomain() && c.ListenOn.Domain() == "localhost")
|
||||||
|
if listenIP {
|
||||||
|
// Listen on specific IP, must set PortRange
|
||||||
|
if c.PortRange == nil {
|
||||||
|
return nil, newError("Listen on specific ip without port in InboundDetour.")
|
||||||
|
}
|
||||||
|
// Listen on IP:Port
|
||||||
|
receiverSettings.PortRange = c.PortRange.Build()
|
||||||
|
} else if listenDS {
|
||||||
|
if c.PortRange != nil {
|
||||||
|
// Listen on Unix Domain Socket, PortRange should be nil
|
||||||
|
receiverSettings.PortRange = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return nil, newError("unable to listen on domain address: ", c.ListenOn.Domain())
|
return nil, newError("unable to listen on domain address: ", c.ListenOn.Domain())
|
||||||
}
|
}
|
||||||
receiverSettings.Listen = c.ListenOn.Build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Allocation != nil {
|
if c.Allocation != nil {
|
||||||
concurrency := -1
|
concurrency := -1
|
||||||
if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" {
|
if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" {
|
||||||
|
@ -100,7 +100,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
case '@', '/':
|
case '@', '/':
|
||||||
fb.Type = "unix"
|
fb.Type = "unix"
|
||||||
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && runtime.GOOS == "linux" {
|
if fb.Dest[0] == '@' && len(fb.Dest) > 1 && fb.Dest[1] == '@' && runtime.GOOS == "linux" {
|
||||||
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work in front of haproxy
|
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
|
||||||
copy(fullAddr, fb.Dest[1:])
|
copy(fullAddr, fb.Dest[1:])
|
||||||
fb.Dest = string(fullAddr)
|
fb.Dest = string(fullAddr)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (s *Server) policy() policy.Session {
|
|||||||
|
|
||||||
// Network implements proxy.Inbound.
|
// Network implements proxy.Inbound.
|
||||||
func (*Server) Network() []net.Network {
|
func (*Server) Network() []net.Network {
|
||||||
return []net.Network{net.Network_TCP}
|
return []net.Network{net.Network_TCP, net.Network_UNIX}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTimeout(err error) bool {
|
func isTimeout(err error) bool {
|
||||||
|
@ -97,7 +97,7 @@ func (s *Server) RemoveUser(ctx context.Context, e string) error {
|
|||||||
|
|
||||||
// Network implements proxy.Inbound.Network().
|
// Network implements proxy.Inbound.Network().
|
||||||
func (s *Server) Network() []net.Network {
|
func (s *Server) Network() []net.Network {
|
||||||
return []net.Network{net.Network_TCP}
|
return []net.Network{net.Network_TCP, net.Network_UNIX}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process implements proxy.Inbound.Process().
|
// Process implements proxy.Inbound.Process().
|
||||||
|
@ -138,7 +138,7 @@ func (h *Handler) RemoveUser(ctx context.Context, e string) error {
|
|||||||
|
|
||||||
// Network implements proxy.Inbound.Network().
|
// Network implements proxy.Inbound.Network().
|
||||||
func (*Handler) Network() []net.Network {
|
func (*Handler) Network() []net.Network {
|
||||||
return []net.Network{net.Network_TCP}
|
return []net.Network{net.Network_TCP, net.Network_UNIX}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process implements proxy.Inbound.Process().
|
// Process implements proxy.Inbound.Process().
|
||||||
|
@ -148,7 +148,7 @@ func (h *Handler) Close() error {
|
|||||||
|
|
||||||
// Network implements proxy.Inbound.Network().
|
// Network implements proxy.Inbound.Network().
|
||||||
func (*Handler) Network() []net.Network {
|
func (*Handler) Network() []net.Network {
|
||||||
return []net.Network{net.Network_TCP}
|
return []net.Network{net.Network_TCP, net.Network_UNIX}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) GetUser(email string) *protocol.MemoryUser {
|
func (h *Handler) GetUser(email string) *protocol.MemoryUser {
|
||||||
|
@ -413,6 +413,7 @@ type SocketConfig struct {
|
|||||||
ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"`
|
ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"`
|
||||||
BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"`
|
BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"`
|
||||||
BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"`
|
BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"`
|
||||||
|
AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SocketConfig) Reset() {
|
func (x *SocketConfig) Reset() {
|
||||||
@ -489,6 +490,13 @@ func (x *SocketConfig) GetBindPort() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SocketConfig) GetAcceptProxyProtocol() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.AcceptProxyProtocol
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_config_proto_rawDesc = []byte{
|
var file_transport_internet_config_proto_rawDesc = []byte{
|
||||||
@ -540,7 +548,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74,
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x1f, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x1f, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xad, 0x03, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0xe1, 0x03, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65,
|
||||||
0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18,
|
0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x4e, 0x0a, 0x03, 0x74,
|
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x4e, 0x0a, 0x03, 0x74,
|
||||||
0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79,
|
0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79,
|
||||||
@ -560,27 +568,30 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05,
|
0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05,
|
||||||
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||||
0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06,
|
0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06,
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x35,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x32,
|
||||||
0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61,
|
0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70,
|
||||||
0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06,
|
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61,
|
||||||
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61,
|
0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||||
0x62, 0x6c, 0x65, 0x10, 0x02, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d,
|
0x6f, 0x6c, 0x22, 0x35, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65,
|
||||||
0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06,
|
0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00,
|
||||||
0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69,
|
0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07,
|
||||||
0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72,
|
||||||
0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54,
|
0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00,
|
||||||
0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a,
|
0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08,
|
||||||
0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f,
|
0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04,
|
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12,
|
||||||
0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74,
|
0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10,
|
||||||
0x10, 0x05, 0x42, 0x68, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e,
|
0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57,
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54,
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x21, 0x76, 0x32, 0x72, 0x61, 0x79,
|
0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x42, 0x68, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32,
|
||||||
0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||||
0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x21, 0x76,
|
||||||
0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72,
|
0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x33,
|
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||||
|
0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72,
|
||||||
|
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -31,7 +31,7 @@ message TransportConfig {
|
|||||||
|
|
||||||
message StreamConfig {
|
message StreamConfig {
|
||||||
// Effective network. Deprecated. Use the string form below.
|
// Effective network. Deprecated. Use the string form below.
|
||||||
TransportProtocol protocol = 1 [deprecated = true];
|
TransportProtocol protocol = 1 [ deprecated = true ];
|
||||||
|
|
||||||
// Effective network.
|
// Effective network.
|
||||||
string protocol_name = 5;
|
string protocol_name = 5;
|
||||||
@ -47,9 +47,7 @@ message StreamConfig {
|
|||||||
SocketConfig socket_settings = 6;
|
SocketConfig socket_settings = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ProxyConfig {
|
message ProxyConfig { string tag = 1; }
|
||||||
string tag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SocketConfig is options to be applied on network sockets.
|
// SocketConfig is options to be applied on network sockets.
|
||||||
message SocketConfig {
|
message SocketConfig {
|
||||||
@ -87,4 +85,6 @@ message SocketConfig {
|
|||||||
bytes bind_address = 5;
|
bytes bind_address = 5;
|
||||||
|
|
||||||
uint32 bind_port = 6;
|
uint32 bind_port = 6;
|
||||||
|
|
||||||
|
bool accept_proxy_protocol = 7;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,7 @@ type Config struct {
|
|||||||
Abstract bool `protobuf:"varint,2,opt,name=abstract,proto3" json:"abstract,omitempty"`
|
Abstract bool `protobuf:"varint,2,opt,name=abstract,proto3" json:"abstract,omitempty"`
|
||||||
// Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to
|
// Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to
|
||||||
// connect(2) or bind(2) when using abstract UDS.
|
// connect(2) or bind(2) when using abstract UDS.
|
||||||
Padding bool `protobuf:"varint,3,opt,name=padding,proto3" json:"padding,omitempty"`
|
Padding bool `protobuf:"varint,3,opt,name=padding,proto3" json:"padding,omitempty"`
|
||||||
AcceptProxyProtocol bool `protobuf:"varint,4,opt,name=acceptProxyProtocol,proto3" json:"acceptProxyProtocol,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@ -96,13 +95,6 @@ func (x *Config) GetPadding() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetAcceptProxyProtocol() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.AcceptProxyProtocol
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_domainsocket_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_domainsocket_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_domainsocket_config_proto_rawDesc = []byte{
|
var file_transport_internet_domainsocket_config_proto_rawDesc = []byte{
|
||||||
@ -111,25 +103,22 @@ var file_transport_internet_domainsocket_config_proto_rawDesc = []byte{
|
|||||||
0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a,
|
0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2a,
|
||||||
0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
||||||
0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f,
|
0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x84, 0x01, 0x0a, 0x06, 0x43,
|
0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x52, 0x0a, 0x06, 0x43, 0x6f,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x62, 0x73,
|
0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x62, 0x73, 0x74,
|
||||||
0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x62, 0x73,
|
0x72, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x62, 0x73, 0x74,
|
||||||
0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
|
0x72, 0x61, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x18,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x12,
|
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x8f,
|
||||||
0x30, 0x0a, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72,
|
0x01, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63,
|
0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
||||||
0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63, 0x6b, 0x65,
|
||||||
0x6c, 0x42, 0x8f, 0x01, 0x0a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e,
|
0x74, 0x50, 0x01, 0x5a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63,
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e,
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x6f, 0x63,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
0x6b, 0x65, 0x74, 0xaa, 0x02, 0x2a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65,
|
||||||
0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74,
|
||||||
0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0xaa, 0x02, 0x2a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43,
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e,
|
|
||||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63,
|
|
||||||
0x6b, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -17,5 +17,4 @@ message Config {
|
|||||||
// Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to
|
// Some apps, eg. haproxy, use the full length of sockaddr_un.sun_path to
|
||||||
// connect(2) or bind(2) when using abstract UDS.
|
// connect(2) or bind(2) when using abstract UDS.
|
||||||
bool padding = 3;
|
bool padding = 3;
|
||||||
bool acceptProxyProtocol = 4;
|
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pires/go-proxyproto"
|
|
||||||
goxtls "github.com/xtls/go"
|
goxtls "github.com/xtls/go"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/session"
|
|
||||||
"v2ray.com/core/transport/internet"
|
"v2ray.com/core/transport/internet"
|
||||||
"v2ray.com/core/transport/internet/tls"
|
"v2ray.com/core/transport/internet/tls"
|
||||||
"v2ray.com/core/transport/internet/xtls"
|
"v2ray.com/core/transport/internet/xtls"
|
||||||
@ -44,23 +42,11 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
return nil, newError("failed to listen domain socket").Base(err).AtWarning()
|
return nil, newError("failed to listen domain socket").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
var ln *Listener
|
ln := &Listener{
|
||||||
if settings.AcceptProxyProtocol {
|
addr: addr,
|
||||||
policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil }
|
ln: unixListener,
|
||||||
ln = &Listener{
|
config: settings,
|
||||||
addr: addr,
|
addConn: handler,
|
||||||
ln: &proxyproto.Listener{Listener: unixListener, Policy: policyFunc},
|
|
||||||
config: settings,
|
|
||||||
addConn: handler,
|
|
||||||
}
|
|
||||||
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
} else {
|
|
||||||
ln = &Listener{
|
|
||||||
addr: addr,
|
|
||||||
ln: unixListener,
|
|
||||||
config: settings,
|
|
||||||
addConn: handler,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !settings.Abstract {
|
if !settings.Abstract {
|
||||||
|
11
transport/internet/filelocker.go
Normal file
11
transport/internet/filelocker.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package internet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileLocker is UDS access lock
|
||||||
|
type FileLocker struct {
|
||||||
|
path string
|
||||||
|
file *os.File
|
||||||
|
}
|
36
transport/internet/filelocker_other.go
Normal file
36
transport/internet/filelocker_other.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package internet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Acquire lock
|
||||||
|
func (fl *FileLocker) Acquire() error {
|
||||||
|
f, err := os.Create(fl.path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := unix.Flock(int(f.Fd()), unix.LOCK_EX); err != nil {
|
||||||
|
f.Close()
|
||||||
|
return newError("failed to lock file: ", fl.path).Base(err)
|
||||||
|
}
|
||||||
|
fl.file = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release lock
|
||||||
|
func (fl *FileLocker) Release() {
|
||||||
|
if err := unix.Flock(int(fl.file.Fd()), unix.LOCK_UN); err != nil {
|
||||||
|
newError("failed to unlock file: ", fl.path).Base(err).WriteToLog()
|
||||||
|
}
|
||||||
|
if err := fl.file.Close(); err != nil {
|
||||||
|
newError("failed to close file: ", fl.path).Base(err).WriteToLog()
|
||||||
|
}
|
||||||
|
if err := os.Remove(fl.path); err != nil {
|
||||||
|
newError("failed to remove file: ", fl.path).Base(err).WriteToLog()
|
||||||
|
}
|
||||||
|
}
|
11
transport/internet/filelocker_windows.go
Normal file
11
transport/internet/filelocker_windows.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package internet
|
||||||
|
|
||||||
|
// Acquire lock
|
||||||
|
func (fl *FileLocker) Acquire() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release lock
|
||||||
|
func (fl *FileLocker) Release() {
|
||||||
|
return
|
||||||
|
}
|
@ -4,8 +4,10 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -27,6 +29,7 @@ type Listener struct {
|
|||||||
handler internet.ConnHandler
|
handler internet.ConnHandler
|
||||||
local net.Addr
|
local net.Addr
|
||||||
config *Config
|
config *Config
|
||||||
|
locker *internet.FileLocker // for unix domain socket
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) Addr() net.Addr {
|
func (l *Listener) Addr() net.Addr {
|
||||||
@ -34,6 +37,10 @@ func (l *Listener) Addr() net.Addr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Listener) Close() error {
|
func (l *Listener) Close() error {
|
||||||
|
if l.locker != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "RELEASE LOCK")
|
||||||
|
l.locker.Release()
|
||||||
|
}
|
||||||
return l.server.Close()
|
return l.server.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +92,10 @@ func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request)
|
|||||||
|
|
||||||
forwardedAddrs := http_proto.ParseXForwardedFor(request.Header)
|
forwardedAddrs := http_proto.ParseXForwardedFor(request.Header)
|
||||||
if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
|
if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
|
||||||
remoteAddr.(*net.TCPAddr).IP = forwardedAddrs[0].IP()
|
remoteAddr = &net.TCPAddr{
|
||||||
|
IP: forwardedAddrs[0].IP(),
|
||||||
|
Port: int(0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done := done.New()
|
done := done.New()
|
||||||
@ -102,13 +112,25 @@ func (l *Listener) ServeHTTP(writer http.ResponseWriter, request *http.Request)
|
|||||||
|
|
||||||
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
||||||
httpSettings := streamSettings.ProtocolSettings.(*Config)
|
httpSettings := streamSettings.ProtocolSettings.(*Config)
|
||||||
listener := &Listener{
|
var listener *Listener
|
||||||
handler: handler,
|
if port == net.Port(0) { // unix
|
||||||
local: &net.TCPAddr{
|
listener = &Listener{
|
||||||
IP: address.IP(),
|
handler: handler,
|
||||||
Port: int(port),
|
local: &net.UnixAddr{
|
||||||
},
|
Name: address.Domain(),
|
||||||
config: httpSettings,
|
Net: "unix",
|
||||||
|
},
|
||||||
|
config: httpSettings,
|
||||||
|
}
|
||||||
|
} else { // tcp
|
||||||
|
listener = &Listener{
|
||||||
|
handler: handler,
|
||||||
|
local: &net.TCPAddr{
|
||||||
|
IP: address.IP(),
|
||||||
|
Port: int(port),
|
||||||
|
},
|
||||||
|
config: httpSettings,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var server *http.Server
|
var server *http.Server
|
||||||
@ -130,23 +152,45 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
||||||
|
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
listener.server = server
|
listener.server = server
|
||||||
go func() {
|
go func() {
|
||||||
tcpListener, err := internet.ListenSystem(ctx, &net.TCPAddr{
|
var streamListener net.Listener
|
||||||
IP: address.IP(),
|
var err error
|
||||||
Port: int(port),
|
if port == net.Port(0) { // unix
|
||||||
}, streamSettings.SocketSettings)
|
streamListener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
||||||
if err != nil {
|
Name: address.Domain(),
|
||||||
newError("failed to listen on", address, ":", port).Base(err).WriteToLog(session.ExportIDToError(ctx))
|
Net: "unix",
|
||||||
return
|
}, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
newError("failed to listen on ", address).Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
locker := ctx.Value(address.Domain())
|
||||||
|
if locker != nil {
|
||||||
|
listener.locker = locker.(*internet.FileLocker)
|
||||||
|
}
|
||||||
|
} else { // tcp
|
||||||
|
streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
||||||
|
IP: address.IP(),
|
||||||
|
Port: int(port),
|
||||||
|
}, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
newError("failed to listen on ", address, ":", port).Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config == nil {
|
if config == nil {
|
||||||
err = server.Serve(tcpListener)
|
err = server.Serve(streamListener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("stoping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("stoping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = server.ServeTLS(tcpListener, "", "")
|
err = server.ServeTLS(streamListener, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("stoping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("stoping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ package internet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/pires/go-proxyproto"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
"v2ray.com/core/common/session"
|
"v2ray.com/core/common/session"
|
||||||
)
|
)
|
||||||
@ -40,10 +42,45 @@ func getControlFunc(ctx context.Context, sockopt *SocketConfig, controllers []co
|
|||||||
|
|
||||||
func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (net.Listener, error) {
|
func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (net.Listener, error) {
|
||||||
var lc net.ListenConfig
|
var lc net.ListenConfig
|
||||||
|
var l net.Listener
|
||||||
|
var err error
|
||||||
|
var network, address string
|
||||||
|
switch addr := addr.(type) {
|
||||||
|
case *net.TCPAddr:
|
||||||
|
network = addr.Network()
|
||||||
|
address = addr.String()
|
||||||
|
lc.Control = getControlFunc(ctx, sockopt, dl.controllers)
|
||||||
|
case *net.UnixAddr:
|
||||||
|
lc.Control = nil
|
||||||
|
network = addr.Network()
|
||||||
|
address = addr.Name
|
||||||
|
if runtime.GOOS == "linux" && address[0] == '@' {
|
||||||
|
// linux abstract unix domain socket is lockfree
|
||||||
|
if len(address) > 1 && address[1] == '@' {
|
||||||
|
// but may need padding to work with haproxy
|
||||||
|
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path))
|
||||||
|
copy(fullAddr, address[1:])
|
||||||
|
address = string(fullAddr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// normal unix domain socket needs lock
|
||||||
|
locker := &FileLocker{
|
||||||
|
path: address + ".lock",
|
||||||
|
}
|
||||||
|
err := locker.Acquire()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx = context.WithValue(ctx, address, locker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lc.Control = getControlFunc(ctx, sockopt, dl.controllers)
|
l, err = lc.Listen(ctx, network, address)
|
||||||
|
if sockopt != nil && sockopt.AcceptProxyProtocol {
|
||||||
return lc.Listen(ctx, addr.Network(), addr.String())
|
policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil }
|
||||||
|
l = &proxyproto.Listener{Listener: l, Policy: policyFunc}
|
||||||
|
}
|
||||||
|
return l, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dl *DefaultListener) ListenPacket(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (net.PacketConn, error) {
|
func (dl *DefaultListener) ListenPacket(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (net.PacketConn, error) {
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pires/go-proxyproto"
|
|
||||||
goxtls "github.com/xtls/go"
|
goxtls "github.com/xtls/go"
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
@ -27,37 +26,53 @@ type Listener struct {
|
|||||||
authConfig internet.ConnectionAuthenticator
|
authConfig internet.ConnectionAuthenticator
|
||||||
config *Config
|
config *Config
|
||||||
addConn internet.ConnHandler
|
addConn internet.ConnHandler
|
||||||
|
locker *internet.FileLocker // for unix domain socket
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenTCP creates a new Listener based on configurations.
|
// ListenTCP creates a new Listener based on configurations.
|
||||||
func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
||||||
listener, err := internet.ListenSystem(ctx, &net.TCPAddr{
|
l := &Listener{
|
||||||
IP: address.IP(),
|
addConn: handler,
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to listen TCP on", address, ":", port).Base(err)
|
|
||||||
}
|
}
|
||||||
newError("listening TCP on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
|
|
||||||
tcpSettings := streamSettings.ProtocolSettings.(*Config)
|
tcpSettings := streamSettings.ProtocolSettings.(*Config)
|
||||||
var l *Listener
|
l.config = tcpSettings
|
||||||
|
if l.config != nil {
|
||||||
if tcpSettings.AcceptProxyProtocol {
|
if streamSettings.SocketSettings == nil {
|
||||||
policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil }
|
streamSettings.SocketSettings = &internet.SocketConfig{}
|
||||||
l = &Listener{
|
|
||||||
listener: &proxyproto.Listener{Listener: listener, Policy: policyFunc},
|
|
||||||
config: tcpSettings,
|
|
||||||
addConn: handler,
|
|
||||||
}
|
|
||||||
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
} else {
|
|
||||||
l = &Listener{
|
|
||||||
listener: listener,
|
|
||||||
config: tcpSettings,
|
|
||||||
addConn: handler,
|
|
||||||
}
|
}
|
||||||
|
streamSettings.SocketSettings.AcceptProxyProtocol = l.config.AcceptProxyProtocol
|
||||||
}
|
}
|
||||||
|
var listener net.Listener
|
||||||
|
var err error
|
||||||
|
if port == net.Port(0) { //unix
|
||||||
|
listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
||||||
|
Name: address.Domain(),
|
||||||
|
Net: "unix",
|
||||||
|
}, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to listen Unix Doman Socket on ", address).Base(err)
|
||||||
|
}
|
||||||
|
newError("listening Unix Domain Socket on ", address).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
locker := ctx.Value(address.Domain())
|
||||||
|
if locker != nil {
|
||||||
|
l.locker = locker.(*internet.FileLocker)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
||||||
|
IP: address.IP(),
|
||||||
|
Port: int(port),
|
||||||
|
}, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to listen TCP on ", address, ":", port).Base(err)
|
||||||
|
}
|
||||||
|
newError("listening TCP on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
||||||
|
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
l.listener = listener
|
||||||
|
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
l.tlsConfig = config.GetTLSConfig(tls.WithNextProto("h2"))
|
l.tlsConfig = config.GetTLSConfig(tls.WithNextProto("h2"))
|
||||||
@ -117,6 +132,9 @@ func (v *Listener) Addr() net.Addr {
|
|||||||
|
|
||||||
// Close implements internet.Listener.Close.
|
// Close implements internet.Listener.Close.
|
||||||
func (v *Listener) Close() error {
|
func (v *Listener) Close() error {
|
||||||
|
if v.locker != nil {
|
||||||
|
v.locker.Release()
|
||||||
|
}
|
||||||
return v.listener.Close()
|
return v.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,27 @@ type Listener interface {
|
|||||||
Addr() net.Addr
|
Addr() net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListenUnix is the UDS version of ListenTCP
|
||||||
|
func ListenUnix(ctx context.Context, address net.Address, settings *MemoryStreamConfig, handler ConnHandler) (Listener, error) {
|
||||||
|
if settings == nil {
|
||||||
|
s, err := ToMemoryStreamConfig(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to create default unix stream settings").Base(err)
|
||||||
|
}
|
||||||
|
settings = s
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol := settings.ProtocolName
|
||||||
|
listenFunc := transportListenerCache[protocol]
|
||||||
|
if listenFunc == nil {
|
||||||
|
return nil, newError(protocol, " unix istener not registered.").AtError()
|
||||||
|
}
|
||||||
|
listener, err := listenFunc(ctx, address, net.Port(0), settings, handler)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to listen on unix address: ", address).Base(err)
|
||||||
|
}
|
||||||
|
return listener, nil
|
||||||
|
}
|
||||||
func ListenTCP(ctx context.Context, address net.Address, port net.Port, settings *MemoryStreamConfig, handler ConnHandler) (Listener, error) {
|
func ListenTCP(ctx context.Context, address net.Address, port net.Port, settings *MemoryStreamConfig, handler ConnHandler) (Listener, error) {
|
||||||
if settings == nil {
|
if settings == nil {
|
||||||
s, err := ToMemoryStreamConfig(nil)
|
s, err := ToMemoryStreamConfig(nil)
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/pires/go-proxyproto"
|
|
||||||
|
|
||||||
"v2ray.com/core/common"
|
"v2ray.com/core/common"
|
||||||
"v2ray.com/core/common/net"
|
"v2ray.com/core/common/net"
|
||||||
@ -48,7 +47,10 @@ func (h *requestHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
|
|||||||
forwardedAddrs := http_proto.ParseXForwardedFor(request.Header)
|
forwardedAddrs := http_proto.ParseXForwardedFor(request.Header)
|
||||||
remoteAddr := conn.RemoteAddr()
|
remoteAddr := conn.RemoteAddr()
|
||||||
if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
|
if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() {
|
||||||
remoteAddr.(*net.TCPAddr).IP = forwardedAddrs[0].IP()
|
remoteAddr = &net.TCPAddr{
|
||||||
|
IP: forwardedAddrs[0].IP(),
|
||||||
|
Port: int(0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ln.addConn(newConnection(conn, remoteAddr))
|
h.ln.addConn(newConnection(conn, remoteAddr))
|
||||||
@ -60,23 +62,48 @@ type Listener struct {
|
|||||||
listener net.Listener
|
listener net.Listener
|
||||||
config *Config
|
config *Config
|
||||||
addConn internet.ConnHandler
|
addConn internet.ConnHandler
|
||||||
|
locker *internet.FileLocker // for unix domain socket
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) {
|
func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, addConn internet.ConnHandler) (internet.Listener, error) {
|
||||||
listener, err := internet.ListenSystem(ctx, &net.TCPAddr{
|
l := &Listener{
|
||||||
IP: address.IP(),
|
addConn: addConn,
|
||||||
Port: int(port),
|
|
||||||
}, streamSettings.SocketSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to listen TCP(for WS) on", address, ":", port).Base(err)
|
|
||||||
}
|
}
|
||||||
newError("listening TCP(for WS) on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
|
|
||||||
wsSettings := streamSettings.ProtocolSettings.(*Config)
|
wsSettings := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
l.config = wsSettings
|
||||||
|
if l.config != nil {
|
||||||
|
if streamSettings.SocketSettings == nil {
|
||||||
|
streamSettings.SocketSettings = &internet.SocketConfig{}
|
||||||
|
}
|
||||||
|
streamSettings.SocketSettings.AcceptProxyProtocol = l.config.AcceptProxyProtocol
|
||||||
|
}
|
||||||
|
var listener net.Listener
|
||||||
|
var err error
|
||||||
|
if port == net.Port(0) { //unix
|
||||||
|
listener, err = internet.ListenSystem(ctx, &net.UnixAddr{
|
||||||
|
Name: address.Domain(),
|
||||||
|
Net: "unix",
|
||||||
|
}, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to listen unix domain socket(for WS) on ", address).Base(err)
|
||||||
|
}
|
||||||
|
newError("listening unix domain socket(for WS) on ", address).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
locker := ctx.Value(address.Domain())
|
||||||
|
if locker != nil {
|
||||||
|
l.locker = locker.(*internet.FileLocker)
|
||||||
|
}
|
||||||
|
} else { //tcp
|
||||||
|
listener, err = internet.ListenSystem(ctx, &net.TCPAddr{
|
||||||
|
IP: address.IP(),
|
||||||
|
Port: int(port),
|
||||||
|
}, streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to listen TCP(for WS) on ", address, ":", port).Base(err)
|
||||||
|
}
|
||||||
|
newError("listening TCP(for WS) on ", address, ":", port).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
if wsSettings.AcceptProxyProtocol {
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.AcceptProxyProtocol {
|
||||||
policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil }
|
|
||||||
listener = &proxyproto.Listener{Listener: listener, Policy: policyFunc}
|
|
||||||
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,11 +113,7 @@ func ListenWS(ctx context.Context, address net.Address, port net.Port, streamSet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
l := &Listener{
|
l.listener = listener
|
||||||
config: wsSettings,
|
|
||||||
addConn: addConn,
|
|
||||||
listener: listener,
|
|
||||||
}
|
|
||||||
|
|
||||||
l.server = http.Server{
|
l.server = http.Server{
|
||||||
Handler: &requestHandler{
|
Handler: &requestHandler{
|
||||||
@ -117,6 +140,9 @@ func (ln *Listener) Addr() net.Addr {
|
|||||||
|
|
||||||
// Close implements net.Listener.Close().
|
// Close implements net.Listener.Close().
|
||||||
func (ln *Listener) Close() error {
|
func (ln *Listener) Close() error {
|
||||||
|
if ln.locker != nil {
|
||||||
|
ln.locker.Release()
|
||||||
|
}
|
||||||
return ln.listener.Close()
|
return ln.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user