Skip to content

Commit 91b7a8b

Browse files
committed
fix: make fwmark linux-specific functionality
1 parent d34de28 commit 91b7a8b

File tree

7 files changed

+176
-48
lines changed

7 files changed

+176
-48
lines changed

cmd/outline-ss-server/config_example.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ services:
2929
secret: Secret1
3030
dialer:
3131
# fwmark can be used in conjunction with other Linux networking features like cgroups, network namespaces, and TC (Traffic Control) for sophisticated network management.
32-
# Value of 0 disables fwmark (SO_MARK)
32+
# Value of 0 disables fwmark (SO_MARK) (Linux Only)
3333
fwmark: 0
3434
- listeners:
3535
- type: tcp

service/tcp.go

-20
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ import (
2424
"log/slog"
2525
"net"
2626
"net/netip"
27-
"os"
2827
"sync"
29-
"syscall"
3028
"time"
3129

3230
"github.com/Jigsaw-Code/outline-sdk/transport"
@@ -168,24 +166,6 @@ func NewStreamHandler(authenticate StreamAuthenticateFunc, timeout time.Duration
168166
}
169167
}
170168

171-
func MakeValidatingTCPStreamDialer(targetIPValidator onet.TargetIPValidator, fwmark uint) transport.StreamDialer {
172-
return &transport.TCPDialer{Dialer: net.Dialer{Control: func(network, address string, c syscall.RawConn) error {
173-
if fwmark > 0 {
174-
err := c.Control(func(fd uintptr) {
175-
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(fwmark))
176-
if err != nil {
177-
slog.Error("Set fwmark failed.", "err", os.NewSyscallError("failed to set mark for TCP socket", err))
178-
}
179-
})
180-
if err != nil {
181-
slog.Error("Set TCPDialer Control func failed.", "err", err)
182-
}
183-
}
184-
ip, _, _ := net.SplitHostPort(address)
185-
return targetIPValidator(net.ParseIP(ip))
186-
}}}
187-
}
188-
189169
// StreamHandler is a handler that handles stream connections.
190170
type StreamHandler interface {
191171
Handle(ctx context.Context, conn transport.StreamConn, connMetrics TCPConnMetrics)

service/tcp_linux.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2018 Jigsaw Operations LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build linux
16+
17+
package service
18+
19+
import (
20+
"log/slog"
21+
"net"
22+
"os"
23+
"syscall"
24+
25+
"github.com/Jigsaw-Code/outline-sdk/transport"
26+
27+
onet "github.com/Jigsaw-Code/outline-ss-server/net"
28+
)
29+
30+
// fwmark can be used in conjunction with other Linux networking features like cgroups, network namespaces, and TC (Traffic Control) for sophisticated network management.
31+
// Value of 0 disables fwmark (SO_MARK) (Linux Only)
32+
func MakeValidatingTCPStreamDialer(targetIPValidator onet.TargetIPValidator, fwmark uint) transport.StreamDialer {
33+
return &transport.TCPDialer{Dialer: net.Dialer{Control: func(network, address string, c syscall.RawConn) error {
34+
if fwmark > 0 {
35+
err := c.Control(func(fd uintptr) {
36+
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(fwmark))
37+
if err != nil {
38+
slog.Error("Set fwmark failed.", "err", os.NewSyscallError("failed to set mark for TCP socket", err))
39+
}
40+
})
41+
if err != nil {
42+
slog.Error("Set TCPDialer Control func failed.", "err", err)
43+
return err
44+
}
45+
}
46+
ip, _, _ := net.SplitHostPort(address)
47+
return targetIPValidator(net.ParseIP(ip))
48+
}}}
49+
}

service/tcp_other.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2018 Jigsaw Operations LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build !linux
16+
17+
package service
18+
19+
import (
20+
"net"
21+
"syscall"
22+
23+
"github.com/Jigsaw-Code/outline-sdk/transport"
24+
25+
onet "github.com/Jigsaw-Code/outline-ss-server/net"
26+
)
27+
28+
// fwmark can be used in conjunction with other Linux networking features like cgroups, network namespaces, and TC (Traffic Control) for sophisticated network management.
29+
// Value of 0 disables fwmark (SO_MARK) (Linux Only)
30+
func MakeValidatingTCPStreamDialer(targetIPValidator onet.TargetIPValidator, fwmark uint) transport.StreamDialer {
31+
return &transport.TCPDialer{Dialer: net.Dialer{Control: func(network, address string, c syscall.RawConn) error {
32+
ip, _, _ := net.SplitHostPort(address)
33+
return targetIPValidator(net.ParseIP(ip))
34+
}}}
35+
}

service/udp.go

-27
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ import (
2020
"log/slog"
2121
"net"
2222
"net/netip"
23-
"os"
2423
"runtime/debug"
2524
"sync"
26-
"syscall"
2725
"time"
2826

2927
"github.com/Jigsaw-Code/outline-sdk/transport/shadowsocks"
@@ -98,31 +96,6 @@ func NewPacketHandler(natTimeout time.Duration, cipherList CipherList, m UDPMetr
9896
return &packetHandler{natTimeout: natTimeout, ciphers: cipherList, m: m, ssm: ssMetrics, targetIPValidator: onet.RequirePublicIP, dialer: dialer}
9997
}
10098

101-
// fwmark can be used in conjunction with other Linux networking features like cgroups, network namespaces, and TC (Traffic Control) for sophisticated network management.
102-
// Value of 0 disables fwmark (SO_MARK)
103-
func MakeTargetPacketListener(fwmark uint) UDPDialer {
104-
return func() (net.PacketConn, *onet.ConnectionError) {
105-
udpConn, err := net.ListenPacket("udp", "")
106-
if err != nil {
107-
return nil, onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to create UDP socket", err)
108-
}
109-
110-
if fwmark > 0 {
111-
file, err := udpConn.(*net.UDPConn).File()
112-
if err != nil {
113-
return nil, onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to get UDP socket file", err)
114-
}
115-
defer file.Close()
116-
117-
err = syscall.SetsockoptInt(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_MARK, int(fwmark))
118-
if err != nil {
119-
slog.Error("Set fwmark failed.", "err", os.NewSyscallError("failed to set mark for UDP socket", err))
120-
}
121-
}
122-
return udpConn, nil
123-
}
124-
}
125-
12699
// PacketHandler is a running UDP shadowsocks proxy that can be stopped.
127100
type PacketHandler interface {
128101
// SetTargetIPValidator sets the function to be used to validate the target IP addresses.

service/udp_linux.go

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2018 Jigsaw Operations LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build linux
16+
17+
package service
18+
19+
import (
20+
"log/slog"
21+
"net"
22+
"os"
23+
"syscall"
24+
25+
onet "github.com/Jigsaw-Code/outline-ss-server/net"
26+
)
27+
28+
// fwmark can be used in conjunction with other Linux networking features like cgroups, network namespaces, and TC (Traffic Control) for sophisticated network management.
29+
// Value of 0 disables fwmark (SO_MARK) (Linux Only)
30+
func MakeTargetPacketListener(fwmark uint) UDPDialer {
31+
return func() (net.PacketConn, *onet.ConnectionError) {
32+
udpConn, err := net.ListenPacket("udp", "")
33+
if err != nil {
34+
return nil, onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to create UDP socket", err)
35+
}
36+
37+
if fwmark > 0 {
38+
rawConn, err := udpConn.(*net.UDPConn).SyscallConn()
39+
if err != nil {
40+
udpConn.Close()
41+
return nil, onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to get UDP raw connection", err)
42+
}
43+
err = rawConn.Control(func(fd uintptr) {
44+
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(fwmark))
45+
if err != nil {
46+
slog.Error("Set fwmark failed.", "err", os.NewSyscallError("failed to set fwmark for UDP socket", err))
47+
}
48+
})
49+
if err != nil {
50+
udpConn.Close()
51+
return nil, onet.NewConnectionError("ERR_CREATE_SOCKET", "Set UDPDialer Control func failed.", err)
52+
}
53+
}
54+
return udpConn, nil
55+
}
56+
}

service/udp_other.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2018 Jigsaw Operations LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build !linux
16+
17+
package service
18+
19+
import (
20+
"net"
21+
22+
onet "github.com/Jigsaw-Code/outline-ss-server/net"
23+
)
24+
25+
// fwmark can be used in conjunction with other Linux networking features like cgroups, network namespaces, and TC (Traffic Control) for sophisticated network management.
26+
// Value of 0 disables fwmark (SO_MARK)
27+
func MakeTargetPacketListener(fwmark uint) UDPDialer {
28+
return func() (net.PacketConn, *onet.ConnectionError) {
29+
udpConn, err := net.ListenPacket("udp", "")
30+
if err != nil {
31+
return nil, onet.NewConnectionError("ERR_CREATE_SOCKET", "Failed to create UDP socket", err)
32+
}
33+
return udpConn, nil
34+
}
35+
}

0 commit comments

Comments
 (0)