5
5
"fmt"
6
6
"io"
7
7
"net"
8
+ "os"
8
9
"regexp"
9
10
"strconv"
10
11
@@ -23,15 +24,24 @@ type cookieAddr struct {
23
24
24
25
// Format:
25
26
// remote_port:local_address:local_port
26
- var remoteForwardRegex = regexp .MustCompile (`^(\d+):(.+):(\d+)$` )
27
+ var remoteForwardRegexTCP = regexp .MustCompile (`^(\d+):(.+):(\d+)$` )
27
28
28
- func validateRemoteForward (flag string ) bool {
29
- return remoteForwardRegex .MatchString (flag )
29
+ // remote_socket_path:local_socket_path (both absolute paths)
30
+ var remoteForwardRegexUnixSocket = regexp .MustCompile (`^(\/.+):(\/.+)$` )
31
+
32
+ func isRemoteForwardTCP (flag string ) bool {
33
+ return remoteForwardRegexTCP .MatchString (flag )
30
34
}
31
35
32
- func parseRemoteForward (flag string ) (net.Addr , net.Addr , error ) {
33
- matches := remoteForwardRegex .FindStringSubmatch (flag )
36
+ func isRemoteForwardUnixSocket (flag string ) bool {
37
+ return remoteForwardRegexUnixSocket .MatchString (flag )
38
+ }
39
+
40
+ func validateRemoteForward (flag string ) bool {
41
+ return isRemoteForwardTCP (flag ) || isRemoteForwardUnixSocket (flag )
42
+ }
34
43
44
+ func parseRemoteForwardTCP (matches []string ) (net.Addr , net.Addr , error ) {
35
45
remotePort , err := strconv .Atoi (matches [1 ])
36
46
if err != nil {
37
47
return nil , nil , xerrors .Errorf ("remote port is invalid: %w" , err )
@@ -57,6 +67,46 @@ func parseRemoteForward(flag string) (net.Addr, net.Addr, error) {
57
67
return localAddr , remoteAddr , nil
58
68
}
59
69
70
+ func parseRemoteForwardUnixSocket (matches []string ) (net.Addr , net.Addr , error ) {
71
+ remoteSocket := matches [1 ]
72
+ localSocket := matches [2 ]
73
+
74
+ fileInfo , err := os .Stat (localSocket )
75
+ if err != nil {
76
+ return nil , nil , err
77
+ }
78
+
79
+ if fileInfo .Mode ()& os .ModeSocket == 0 {
80
+ return nil , nil , xerrors .New ("File is not a Unix domain socket file" )
81
+ }
82
+
83
+ remoteAddr := & net.UnixAddr {
84
+ Name : remoteSocket ,
85
+ Net : "unix" ,
86
+ }
87
+
88
+ localAddr := & net.UnixAddr {
89
+ Name : localSocket ,
90
+ Net : "unix" ,
91
+ }
92
+ return localAddr , remoteAddr , nil
93
+ }
94
+
95
+ func parseRemoteForward (flag string ) (net.Addr , net.Addr , error ) {
96
+ tcpMatches := remoteForwardRegexTCP .FindStringSubmatch (flag )
97
+
98
+ if len (tcpMatches ) > 0 {
99
+ return parseRemoteForwardTCP (tcpMatches )
100
+ }
101
+
102
+ unixSocketMatches := remoteForwardRegexUnixSocket .FindStringSubmatch (flag )
103
+ if len (unixSocketMatches ) > 0 {
104
+ return parseRemoteForwardUnixSocket (unixSocketMatches )
105
+ }
106
+
107
+ return nil , nil , xerrors .New ("Could not match forward arguments" )
108
+ }
109
+
60
110
// sshRemoteForward starts forwarding connections from a remote listener to a
61
111
// local address via SSH in a goroutine.
62
112
//
0 commit comments