packetman_linux_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // +build PSIPHON_RUN_PACKET_MANIPULATOR_TEST
  2. /*
  3. * Copyright (c) 2020, Psiphon Inc.
  4. * All rights reserved.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. package packetman
  21. import (
  22. "fmt"
  23. "io"
  24. "io/ioutil"
  25. "net"
  26. "net/http"
  27. "strconv"
  28. "testing"
  29. "time"
  30. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  31. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/stacktrace"
  32. )
  33. func TestPacketManipulatorIPv4(t *testing.T) {
  34. testPacketManipulator(false, t)
  35. }
  36. func TestPacketManipulatorIPv6(t *testing.T) {
  37. testPacketManipulator(true, t)
  38. }
  39. func testPacketManipulator(useIPv6 bool, t *testing.T) {
  40. // Test: run a Manipulator in front of a web server; make an HTTP request;
  41. // the expected transformation spec should be executed (as reported by
  42. // GetAppliedSpecName) and the request must succeed.
  43. ipv4, ipv6, err := common.GetRoutableInterfaceIPAddresses()
  44. if err != nil {
  45. t.Fatalf("GetRoutableInterfaceIPAddressesfailed: %v", err)
  46. }
  47. network := "tcp4"
  48. address := net.JoinHostPort(ipv4.String(), "0")
  49. if useIPv6 {
  50. if ipv6 == nil {
  51. t.Skipf("test unsupported: no IP address")
  52. }
  53. network = "tcp6"
  54. address = net.JoinHostPort(ipv6.String(), "0")
  55. }
  56. listener, err := net.Listen(network, address)
  57. if err != nil {
  58. t.Fatalf("net.Listen failed: %v", err)
  59. }
  60. defer listener.Close()
  61. hostStr, portStr, err := net.SplitHostPort(listener.Addr().String())
  62. if err != nil {
  63. t.Fatalf("net.SplitHostPort failed: %s", err.Error())
  64. }
  65. listenerPort, _ := strconv.Atoi(portStr)
  66. // [["TCP-flags S"]] replaces the original SYN-ACK packet with a single
  67. // SYN packet, implementing TCP simultaneous open.
  68. testSpecName := "test-spec"
  69. extraDataValue := "extra-data"
  70. config := &Config{
  71. Logger: newTestLogger(),
  72. ProtocolPorts: []int{listenerPort},
  73. Specs: []*Spec{&Spec{Name: testSpecName, PacketSpecs: [][]string{[]string{"TCP-flags S"}}}},
  74. SelectSpecName: func(protocolPort int, _ net.IP) (string, interface{}) {
  75. if protocolPort == listenerPort {
  76. return testSpecName, extraDataValue
  77. }
  78. return "", nil
  79. },
  80. QueueNumber: 1,
  81. }
  82. m, err := NewManipulator(config)
  83. if err != nil {
  84. t.Fatalf("NewManipulator failed: %v", err)
  85. }
  86. err = m.Start()
  87. if err != nil {
  88. t.Fatalf("Manipulator.Start failed: %v", err)
  89. }
  90. defer m.Stop()
  91. go func() {
  92. serveMux := http.NewServeMux()
  93. serveMux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
  94. io.WriteString(w, "test-response\n")
  95. })
  96. server := &http.Server{
  97. Handler: serveMux,
  98. ConnState: func(conn net.Conn, state http.ConnState) {
  99. if state == http.StateNew {
  100. localAddr := conn.LocalAddr().(*net.TCPAddr)
  101. remoteAddr := conn.RemoteAddr().(*net.TCPAddr)
  102. specName, extraData, err := m.GetAppliedSpecName(localAddr, remoteAddr)
  103. if err != nil {
  104. t.Fatalf("GetAppliedSpecName failed: %v", err)
  105. }
  106. if specName != testSpecName {
  107. t.Fatalf("unexpected spec name: %s", specName)
  108. }
  109. extraDataStr, ok := extraData.(string)
  110. if !ok || extraDataStr != extraDataValue {
  111. t.Fatalf("unexpected extra data value: %v", extraData)
  112. }
  113. }
  114. },
  115. }
  116. server.Serve(listener)
  117. }()
  118. httpClient := &http.Client{
  119. Timeout: 30 * time.Second,
  120. }
  121. response, err := httpClient.Get(fmt.Sprintf("http://%s:%s", hostStr, portStr))
  122. if err != nil {
  123. t.Fatalf("http.Get failed: %v", err)
  124. }
  125. defer response.Body.Close()
  126. _, err = ioutil.ReadAll(response.Body)
  127. if err != nil {
  128. t.Fatalf("ioutil.ReadAll failed: %v", err)
  129. }
  130. if response.StatusCode != http.StatusOK {
  131. t.Fatalf("unexpected response code: %d", response.StatusCode)
  132. }
  133. }
  134. func newTestLogger() common.Logger {
  135. return &testLogger{}
  136. }
  137. type testLogger struct {
  138. }
  139. func (logger *testLogger) WithTrace() common.LogTrace {
  140. return &testLogTrace{
  141. trace: stacktrace.GetParentFunctionName(),
  142. }
  143. }
  144. func (logger *testLogger) WithTraceFields(fields common.LogFields) common.LogTrace {
  145. return &testLogTrace{
  146. trace: stacktrace.GetParentFunctionName(),
  147. fields: fields,
  148. }
  149. }
  150. func (logger *testLogger) LogMetric(metric string, fields common.LogFields) {
  151. }
  152. type testLogTrace struct {
  153. trace string
  154. fields common.LogFields
  155. }
  156. func (log *testLogTrace) log(
  157. noticeType string, args ...interface{}) {
  158. fmt.Printf("[%s] %s: %+v: %s\n",
  159. noticeType,
  160. log.trace,
  161. log.fields,
  162. fmt.Sprint(args...))
  163. }
  164. func (log *testLogTrace) Debug(args ...interface{}) {
  165. log.log("DEBUG", args...)
  166. }
  167. func (log *testLogTrace) Info(args ...interface{}) {
  168. log.log("INFO", args...)
  169. }
  170. func (log *testLogTrace) Warning(args ...interface{}) {
  171. log.log("ALERT", args...)
  172. }
  173. func (log *testLogTrace) Error(args ...interface{}) {
  174. log.log("ERROR", args...)
  175. }