shadowsocks.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (c) 2024, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package server
  20. import (
  21. "bytes"
  22. "io"
  23. "net"
  24. "github.com/Jigsaw-Code/outline-sdk/transport/shadowsocks"
  25. "github.com/Jigsaw-Code/outline-ss-server/service"
  26. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  27. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  28. )
  29. // ShadowsocksServer tunnels TCP traffic (in the case of Psiphon, SSH traffic)
  30. // over Shadowsocks.
  31. type ShadowsocksServer struct {
  32. support *SupportServices
  33. listener net.Listener
  34. key *shadowsocks.EncryptionKey
  35. saltGenerator service.ServerSaltGenerator
  36. replayCache service.ReplayCache
  37. irregularTunnelLogger func(string, error, common.LogFields)
  38. }
  39. // ListenShadowsocks returns the listener of a new ShadowsocksServer.
  40. func ListenShadowsocks(
  41. support *SupportServices,
  42. listener net.Listener,
  43. ssEncryptionKey string,
  44. irregularTunnelLogger func(string, error, common.LogFields),
  45. ) (net.Listener, error) {
  46. server, err := NewShadowsocksServer(support, listener, ssEncryptionKey, irregularTunnelLogger)
  47. if err != nil {
  48. return nil, errors.Trace(err)
  49. }
  50. return NewShadowsocksListener(listener, server), nil
  51. }
  52. // NewShadowsocksServer initializes a new ShadowsocksServer.
  53. func NewShadowsocksServer(
  54. support *SupportServices,
  55. listener net.Listener,
  56. ssEncryptionKey string,
  57. irregularTunnelLogger func(string, error, common.LogFields)) (*ShadowsocksServer, error) {
  58. // Note: client must use the same cipher.
  59. key, err := shadowsocks.NewEncryptionKey(shadowsocks.CHACHA20IETFPOLY1305, ssEncryptionKey)
  60. if err != nil {
  61. return nil, errors.TraceMsg(err, "shadowsocks.NewEncryptionKey failed")
  62. }
  63. // Note: see comment for service.MaxCapacity for a description of
  64. // the expected false positive rate.
  65. replayHistory := service.MaxCapacity
  66. shadowsocksServer := &ShadowsocksServer{
  67. support: support,
  68. listener: listener,
  69. key: key,
  70. saltGenerator: service.NewServerSaltGenerator(ssEncryptionKey),
  71. replayCache: service.NewReplayCache(replayHistory),
  72. irregularTunnelLogger: irregularTunnelLogger,
  73. }
  74. return shadowsocksServer, nil
  75. }
  76. // ShadowsocksListener implements the net.Listener interface. Accept returns a
  77. // net.Conn which implements the common.MetricsSource interface.
  78. type ShadowsocksListener struct {
  79. net.Listener
  80. server *ShadowsocksServer
  81. }
  82. // NewShadowsocksListener initializes a new ShadowsocksListener.
  83. func NewShadowsocksListener(listener net.Listener, server *ShadowsocksServer) *ShadowsocksListener {
  84. return &ShadowsocksListener{
  85. Listener: listener,
  86. server: server,
  87. }
  88. }
  89. func (l *ShadowsocksListener) Accept() (net.Conn, error) {
  90. conn, err := l.Listener.Accept()
  91. if err != nil {
  92. return nil, errors.Trace(err)
  93. }
  94. reader := NewSaltReader(conn, l.server)
  95. ssr := shadowsocks.NewReader(reader, l.server.key)
  96. ssw := shadowsocks.NewWriter(conn, l.server.key)
  97. ssw.SetSaltGenerator(l.server.saltGenerator)
  98. return NewShadowsocksConn(conn, ssr, ssw), nil
  99. }
  100. // ShadowsocksConn implements the net.Conn and common.MetricsSource interfaces.
  101. type ShadowsocksConn struct {
  102. net.Conn
  103. ssr io.Reader
  104. ssw io.Writer
  105. }
  106. // NewShadowsocksConn initializes a new NewShadowsocksConn.
  107. func NewShadowsocksConn(conn net.Conn, ssr io.Reader, ssw io.Writer) *ShadowsocksConn {
  108. return &ShadowsocksConn{
  109. Conn: conn,
  110. ssr: ssr,
  111. ssw: ssw,
  112. }
  113. }
  114. func (conn *ShadowsocksConn) Read(b []byte) (int, error) {
  115. // TODO: invoke the irregular tunnel logger if Read fails due to an invalid
  116. // message from the client. I.e., client does not know the shadowsocks key.
  117. // Requires enumerating the Read errors that correspond to an invalid
  118. // message because no exported error types, or values, are returned on
  119. // such an error.
  120. return conn.ssr.Read(b)
  121. }
  122. func (conn *ShadowsocksConn) Write(p []byte) (n int, err error) {
  123. return conn.ssw.Write(p)
  124. }
  125. // GetMetrics implements the common.MetricsSource interface.
  126. func (conn *ShadowsocksConn) GetMetrics() common.LogFields {
  127. var logFields common.LogFields
  128. // Relay any metrics from the underlying conn.
  129. if m, ok := conn.Conn.(common.MetricsSource); ok {
  130. logFields = m.GetMetrics()
  131. } else {
  132. logFields = make(common.LogFields)
  133. }
  134. return logFields
  135. }
  136. // Not safe for concurrent use.
  137. type saltReader struct {
  138. net.Conn
  139. server *ShadowsocksServer
  140. reader io.Reader
  141. }
  142. func NewSaltReader(conn net.Conn, server *ShadowsocksServer) *saltReader {
  143. return &saltReader{
  144. Conn: conn,
  145. server: server,
  146. }
  147. }
  148. func (conn *saltReader) Read(b []byte) (int, error) {
  149. if conn.reader == nil {
  150. err := conn.init()
  151. if err != nil {
  152. return 0, errors.Trace(err)
  153. }
  154. }
  155. return conn.reader.Read(b)
  156. }
  157. func (conn *saltReader) init() error {
  158. // Note: code adapted from https://github.com/Jigsaw-Code/outline-ss-server/blob/fa651d3e87cc0a94104babb3ae85253471a22ebc/service/tcp.go#L119.
  159. salt, reader, err := readSalt(conn.Conn, conn.server.key.SaltSize())
  160. if err != nil {
  161. return errors.TraceMsg(err, "failed to read salt")
  162. }
  163. conn.reader = reader
  164. // Hardcode key ID because all clients use the same cipher per server,
  165. // which is fine because the underlying SSH connection protects the
  166. // confidentiality and integrity of client traffic between the client and
  167. // server.
  168. keyID := "1"
  169. isServerSalt := conn.server.saltGenerator.IsServerSalt(salt)
  170. if isServerSalt || !conn.server.replayCache.Add(keyID, salt) {
  171. drainConn(conn.Conn)
  172. var err error
  173. if isServerSalt {
  174. err = errors.TraceNew("server replay detected")
  175. } else {
  176. err = errors.TraceNew("client replay detected")
  177. }
  178. conn.server.irregularTunnelLogger(conn.RemoteAddr().String(), err, nil)
  179. return err
  180. }
  181. return nil
  182. }
  183. func readSalt(conn net.Conn, saltSize int) ([]byte, io.Reader, error) {
  184. salt := make([]byte, saltSize)
  185. if n, err := io.ReadFull(conn, salt); err != nil {
  186. return nil, nil, errors.Tracef("reading conn failed after %d bytes: %w", n, err)
  187. }
  188. return salt, io.MultiReader(bytes.NewReader(salt), conn), nil
  189. }
  190. func drainConn(conn net.Conn) {
  191. _, _ = io.Copy(io.Discard, conn)
  192. conn.Close()
  193. }