Skip to content

Commit 4140bcd

Browse files
Mockingyuhan6665
Mocking
authored andcommitted
Enhancement of "redirect" function, adding support for MacOS
Added the function of "MacOS" FreeBSD firewall traffic forwarding and resolving destination address example: "inbounds": [ { "listen": "127.0.0.1", "port": 1122, "protocol": "dokodemo-door", "tag": "dokodemo", "settings": { "network": "tcp", "followRedirect": true, "userLevel": 0 }, "streamSettings": { "sockopt": { "tproxy": "Redirect" } } } ] 还原#1189 提交
1 parent 59602db commit 4140bcd

File tree

11 files changed

+176
-141
lines changed

11 files changed

+176
-141
lines changed

app/proxyman/inbound/worker.go

-7
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,6 @@ func (w *tcpWorker) callback(conn stat.Connection) {
7272
}
7373
case internet.SocketConfig_TProxy:
7474
dest = net.DestinationFromAddr(conn.LocalAddr())
75-
case internet.SocketConfig_PF:
76-
d, err := net.OriginalDst(conn)
77-
if err != nil {
78-
newError("failed to get original destination").Base(err).WriteToLog(session.ExportIDToError(ctx))
79-
} else {
80-
dest = d
81-
}
8275
}
8376
if dest.IsValid() {
8477
ctx = session.ContextWithOutbound(ctx, &session.Outbound{

common/net/destination-darwin.go

-94
This file was deleted.

common/net/destination-other.go

-8
This file was deleted.

infra/conf/transport_internet.go

-2
Original file line numberDiff line numberDiff line change
@@ -558,8 +558,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
558558
tproxy = internet.SocketConfig_TProxy
559559
case "redirect":
560560
tproxy = internet.SocketConfig_Redirect
561-
case "pf":
562-
tproxy = internet.SocketConfig_PF
563561
default:
564562
tproxy = internet.SocketConfig_Off
565563
}

transport/internet/config.pb.go

+20-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

transport/internet/config.proto

-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ message SocketConfig {
7474
TProxy = 1;
7575
// Redirect mode.
7676
Redirect = 2;
77-
// PF mode.
78-
PF = 3;
7977
}
8078

8179
// TProxy is for enabling TProxy socket option.

transport/internet/sockopt_darwin.go

+81
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package internet
22

33
import (
4+
"github.com/xtls/xray-core/common/net"
45
"golang.org/x/sys/unix"
6+
"os"
7+
"syscall"
8+
"unsafe"
59
)
610

711
const (
@@ -13,6 +17,83 @@ const (
1317
sysTCP_KEEPINTVL = 0x101 // nolint: revive,stylecheck
1418
)
1519

20+
const (
21+
PfOut = 2
22+
IOCOut = 0x40000000
23+
IOCIn = 0x80000000
24+
IOCInOut = IOCIn | IOCOut
25+
IOCPARMMask = 0x1FFF
26+
LEN = 4*16 + 4*4 + 4*1
27+
// #define _IOC(inout,group,num,len) (inout | ((len & IOCPARMMask) << 16) | ((group) << 8) | (num))
28+
// #define _IOWR(g,n,t) _IOC(IOCInOut, (g), (n), sizeof(t))
29+
// #define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook)
30+
DIOCNATLOOK = IOCInOut | ((LEN & IOCPARMMask) << 16) | ('D' << 8) | 23
31+
)
32+
33+
// OriginalDst uses ioctl to read original destination from /dev/pf
34+
func OriginalDst(la, ra net.Addr) (net.IP, int, error) {
35+
f, err := os.Open("/dev/pf")
36+
if err != nil {
37+
return net.IP{}, -1, newError("failed to open device /dev/pf").Base(err)
38+
}
39+
defer f.Close()
40+
fd := f.Fd()
41+
nl := struct { // struct pfioc_natlook
42+
saddr, daddr, rsaddr, rdaddr [16]byte
43+
sxport, dxport, rsxport, rdxport [4]byte
44+
af, proto, protoVariant, direction uint8
45+
}{
46+
af: syscall.AF_INET,
47+
proto: syscall.IPPROTO_TCP,
48+
direction: PfOut,
49+
}
50+
var raIP, laIP net.IP
51+
var raPort, laPort int
52+
switch la.(type) {
53+
case *net.TCPAddr:
54+
raIP = ra.(*net.TCPAddr).IP
55+
laIP = la.(*net.TCPAddr).IP
56+
raPort = ra.(*net.TCPAddr).Port
57+
laPort = la.(*net.TCPAddr).Port
58+
case *net.UDPAddr:
59+
raIP = ra.(*net.UDPAddr).IP
60+
laIP = la.(*net.UDPAddr).IP
61+
raPort = ra.(*net.UDPAddr).Port
62+
laPort = la.(*net.UDPAddr).Port
63+
}
64+
if raIP.To4() != nil {
65+
if laIP.IsUnspecified() {
66+
laIP = net.ParseIP("127.0.0.1")
67+
}
68+
copy(nl.saddr[:net.IPv4len], raIP.To4())
69+
copy(nl.daddr[:net.IPv4len], laIP.To4())
70+
}
71+
if raIP.To16() != nil && raIP.To4() == nil {
72+
if laIP.IsUnspecified() {
73+
laIP = net.ParseIP("::1")
74+
}
75+
copy(nl.saddr[:], raIP)
76+
copy(nl.daddr[:], laIP)
77+
}
78+
nl.sxport[0], nl.sxport[1] = byte(raPort>>8), byte(raPort)
79+
nl.dxport[0], nl.dxport[1] = byte(laPort>>8), byte(laPort)
80+
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, DIOCNATLOOK, uintptr(unsafe.Pointer(&nl))); errno != 0 {
81+
return net.IP{}, -1, os.NewSyscallError("ioctl", err)
82+
}
83+
84+
odPort := nl.rdxport
85+
var odIP net.IP
86+
switch nl.af {
87+
case syscall.AF_INET:
88+
odIP = make(net.IP, net.IPv4len)
89+
copy(odIP, nl.rdaddr[:net.IPv4len])
90+
case syscall.AF_INET6:
91+
odIP = make(net.IP, net.IPv6len)
92+
copy(odIP, nl.rdaddr[:])
93+
}
94+
return odIP, int(net.PortFromBytes(odPort[:2])), nil
95+
}
96+
1697
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
1798
if isTCPSocket(network) {
1899
tfo := config.ParseTFOValue()
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//go:build darwin
2+
// +build darwin
3+
4+
package tcp
5+
6+
import (
7+
"github.com/xtls/xray-core/common/net"
8+
"github.com/xtls/xray-core/transport/internet"
9+
"github.com/xtls/xray-core/transport/internet/stat"
10+
)
11+
12+
// GetOriginalDestination from tcp conn
13+
func GetOriginalDestination(conn stat.Connection) (net.Destination, error) {
14+
la := conn.LocalAddr()
15+
ra := conn.RemoteAddr()
16+
ip, port, err := internet.OriginalDst(la, ra)
17+
if err != nil {
18+
return net.Destination{}, newError("failed to get destination").Base(err)
19+
}
20+
dest := net.TCPDestination(net.IPAddress(ip), net.Port(port))
21+
if !dest.IsValid() {
22+
return net.Destination{}, newError("failed to parse destination.")
23+
}
24+
return dest, nil
25+
}

transport/internet/tcp/sockopt_other.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build !linux && !freebsd
2-
// +build !linux,!freebsd
1+
//go:build !linux && !freebsd && !darwin
2+
// +build !linux,!freebsd,!darwin
33

44
package tcp
55

transport/internet/udp/hub_darwin.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//go:build darwin
2+
// +build darwin
3+
4+
package udp
5+
6+
import (
7+
"bytes"
8+
"encoding/gob"
9+
"io"
10+
11+
"github.com/xtls/xray-core/common/errors"
12+
"github.com/xtls/xray-core/common/net"
13+
"github.com/xtls/xray-core/transport/internet"
14+
)
15+
16+
// RetrieveOriginalDest from stored laddr, caddr
17+
func RetrieveOriginalDest(oob []byte) net.Destination {
18+
dec := gob.NewDecoder(bytes.NewBuffer(oob))
19+
var la, ra net.UDPAddr
20+
dec.Decode(&la)
21+
dec.Decode(&ra)
22+
ip, port, err := internet.OriginalDst(&la, &ra)
23+
if err != nil {
24+
return net.Destination{}
25+
}
26+
return net.UDPDestination(net.IPAddress(ip), net.Port(port))
27+
}
28+
29+
// ReadUDPMsg stores laddr, caddr for later use
30+
func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
31+
nBytes, addr, err := conn.ReadFromUDP(payload)
32+
var buf bytes.Buffer
33+
enc := gob.NewEncoder(&buf)
34+
udpAddr, ok := conn.LocalAddr().(*net.UDPAddr)
35+
if !ok {
36+
return 0, 0, 0, nil, errors.New("invalid local address")
37+
}
38+
if addr == nil {
39+
return 0, 0, 0, nil, errors.New("invalid remote address")
40+
}
41+
enc.Encode(udpAddr)
42+
enc.Encode(addr)
43+
var reader io.Reader = &buf
44+
noob, _ := reader.Read(oob)
45+
return nBytes, noob, 0, addr, err
46+
}

transport/internet/udp/hub_other.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build !linux && !freebsd
2-
// +build !linux,!freebsd
1+
//go:build !linux && !freebsd && !darwin
2+
// +build !linux,!freebsd,!darwin
33

44
package udp
55

0 commit comments

Comments
 (0)