shadowsocksConn.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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 psiphon
  20. import (
  21. "context"
  22. "io"
  23. "net"
  24. "github.com/Jigsaw-Code/outline-sdk/transport/shadowsocks"
  25. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  26. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  27. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  28. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
  29. )
  30. // ShadowsockConfig specifies the behavior of a shadowsocksConn.
  31. type ShadowsockConfig struct {
  32. dialAddr string
  33. key string
  34. prefix *ShadowsocksPrefixSpec
  35. }
  36. // shadowsocksConn is a network connection that tunnels net.Conn flows over Shadowsocks.
  37. type shadowsocksConn struct {
  38. net.Conn
  39. ssw io.Writer
  40. ssr io.Reader
  41. }
  42. // DialShadowsocksTunnel returns an initialized Shadowsocks connection.
  43. func DialShadowsocksTunnel(
  44. ctx context.Context,
  45. shadowsocksConfig *ShadowsockConfig,
  46. dialConfig *DialConfig) (*shadowsocksConn, error) {
  47. // Note: server must use the same cipher.
  48. key, err := shadowsocks.NewEncryptionKey(shadowsocks.CHACHA20IETFPOLY1305, shadowsocksConfig.key)
  49. if err != nil {
  50. return nil, errors.Trace(err)
  51. }
  52. conn, err := DialTCP(ctx, shadowsocksConfig.dialAddr, dialConfig)
  53. if err != nil {
  54. return nil, errors.Trace(err)
  55. }
  56. ssw := shadowsocks.NewWriter(conn, key)
  57. if shadowsocksConfig.prefix != nil {
  58. prefix, err := makePrefix(shadowsocksConfig.prefix)
  59. if err != nil {
  60. return nil, errors.Trace(err)
  61. }
  62. // Prefixes must be <= 16 bytes as longer prefixes risk salt collisions,
  63. // which can compromise the security of the connection [1][2].
  64. // [1] https://developers.google.com/outline/docs/guides/service-providers/prefixing
  65. // [2] See comment for shadowsocks.NewPrefixSaltGenerator
  66. if len(prefix) > 16 {
  67. return nil, errors.Tracef("invalid prefix length %d", len(prefix))
  68. }
  69. ssw.SetSaltGenerator(shadowsocks.NewPrefixSaltGenerator(prefix))
  70. }
  71. return &shadowsocksConn{
  72. Conn: conn,
  73. ssr: shadowsocks.NewReader(conn, key),
  74. ssw: ssw,
  75. }, nil
  76. }
  77. func (conn *shadowsocksConn) Read(p []byte) (n int, err error) {
  78. return conn.ssr.Read(p)
  79. }
  80. func (conn *shadowsocksConn) Write(p []byte) (n int, err error) {
  81. return conn.ssw.Write(p)
  82. }
  83. // GetMetrics implements the common.MetricsSource interface.
  84. func (conn *shadowsocksConn) GetMetrics() common.LogFields {
  85. // Relay any metrics from the underlying conn.
  86. m, ok := conn.Conn.(common.MetricsSource)
  87. if ok {
  88. return m.GetMetrics()
  89. }
  90. return nil
  91. }
  92. func (conn *shadowsocksConn) IsClosed() bool {
  93. closer, ok := conn.Conn.(common.Closer)
  94. if !ok {
  95. return false
  96. }
  97. return closer.IsClosed()
  98. }
  99. type ShadowsocksPrefixSpec struct {
  100. Name string
  101. Spec transforms.Spec
  102. Seed *prng.Seed
  103. }
  104. func makePrefix(spec *ShadowsocksPrefixSpec) ([]byte, error) {
  105. minLength := 0
  106. prefix, _, err := spec.Spec.ApplyPrefix(spec.Seed, minLength)
  107. if err != nil {
  108. return nil, errors.Trace(err)
  109. }
  110. return prefix, nil
  111. }