Tunnel inbound: Support TPROXY on OpenBSD as well (#6546)

https://github.com/XTLS/Xray-core/pull/6546#issuecomment-5100711574
This commit is contained in:
Maksim Varentsov
2026-08-12 04:51:38 +00:00
committed by GitHub
parent bc6e966af8
commit a000371b2a
7 changed files with 211 additions and 6 deletions
+33
View File
@@ -0,0 +1,33 @@
//go:build openbsd
// +build openbsd
package internet
import (
"github.com/xtls/xray-core/common/errors"
"golang.org/x/sys/unix"
)
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
return nil
}
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
if config.ReceiveOriginalDestAddress && isUDPSocket(network) {
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_RECVDSTADDR, 1); err != nil {
return errors.New("failed to set IP_RECVDSTADDR").Base(err)
}
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_RECVDSTPORT, 1); err != nil {
return errors.New("failed to set IP_RECVDSTPORT").Base(err)
}
}
return nil
}
func setReuseAddr(fd uintptr) error {
return nil
}
func setReusePort(fd uintptr) error {
return nil
}
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build js || netbsd || openbsd || solaris
// +build js netbsd openbsd solaris
//go:build js || netbsd || solaris
// +build js netbsd solaris
package internet
+57
View File
@@ -0,0 +1,57 @@
//go:build openbsd
// +build openbsd
package udp
import (
"encoding/binary"
"github.com/xtls/xray-core/common/net"
"golang.org/x/sys/unix"
)
func retrieveOriginalDestFromControlMessages(msgs []unix.SocketControlMessage) net.Destination {
var ip []byte
var port uint16
var haveAddress bool
var havePort bool
for _, msg := range msgs {
if msg.Header.Level != unix.IPPROTO_IP {
continue
}
switch msg.Header.Type {
case unix.IP_RECVDSTADDR:
if len(msg.Data) < 4 {
continue
}
ip = append(ip[:0], msg.Data[:4]...)
haveAddress = true
case unix.IP_RECVDSTPORT:
if len(msg.Data) < 2 {
continue
}
port = binary.BigEndian.Uint16(msg.Data[:2])
havePort = true
}
}
if !haveAddress || !havePort || port == 0 {
return net.Destination{}
}
return net.UDPDestination(net.IPAddress(ip), net.Port(port))
}
func RetrieveOriginalDest(oob []byte) net.Destination {
msgs, err := unix.ParseSocketControlMessage(oob)
if err != nil {
return net.Destination{}
}
return retrieveOriginalDestFromControlMessages(msgs)
}
func ReadUDPMsg(conn *net.UDPConn, payload []byte, oob []byte) (int, int, int, *net.UDPAddr, error) {
return conn.ReadMsgUDP(payload, oob)
}
@@ -0,0 +1,57 @@
//go:build openbsd
// +build openbsd
package udp
import (
"testing"
"golang.org/x/sys/unix"
)
func TestRetrieveOriginalDestFromControlMessages(t *testing.T) {
msgs := []unix.SocketControlMessage{
{
Header: unix.Cmsghdr{Level: unix.IPPROTO_IP, Type: unix.IP_RECVDSTPORT},
Data: []byte{0x30, 0x39},
},
{
Header: unix.Cmsghdr{Level: unix.IPPROTO_IP, Type: unix.IP_RECVDSTADDR},
Data: []byte{203, 0, 113, 7},
},
}
dest := retrieveOriginalDestFromControlMessages(msgs)
if !dest.IsValid() {
t.Fatal("destination is invalid")
}
if got, want := dest.Address.String(), "203.0.113.7"; got != want {
t.Fatalf("address = %q, want %q", got, want)
}
if got, want := dest.Port.Value(), uint16(12345); got != want {
t.Fatalf("port = %d, want %d", got, want)
}
}
func TestRetrieveOriginalDestRequiresAddressAndPort(t *testing.T) {
tests := [][]unix.SocketControlMessage{
{
{
Header: unix.Cmsghdr{Level: unix.IPPROTO_IP, Type: unix.IP_RECVDSTADDR},
Data: []byte{203, 0, 113, 7},
},
},
{
{
Header: unix.Cmsghdr{Level: unix.IPPROTO_IP, Type: unix.IP_RECVDSTPORT},
Data: []byte{0x30, 0x39},
},
},
}
for _, msgs := range tests {
if dest := retrieveOriginalDestFromControlMessages(msgs); dest.IsValid() {
t.Fatalf("unexpected destination: %v", dest)
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build !linux && !freebsd && !darwin
// +build !linux,!freebsd,!darwin
//go:build !linux && !freebsd && !darwin && !openbsd
// +build !linux,!freebsd,!darwin,!openbsd
package udp