server_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /*
  2. * Copyright (c) 2016, 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. "encoding/json"
  22. "errors"
  23. "flag"
  24. "fmt"
  25. "io/ioutil"
  26. "net"
  27. "net/http"
  28. "net/url"
  29. "os"
  30. "strconv"
  31. "sync"
  32. "syscall"
  33. "testing"
  34. "time"
  35. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
  36. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  37. "golang.org/x/net/proxy"
  38. )
  39. func TestMain(m *testing.M) {
  40. flag.Parse()
  41. os.Remove(psiphon.DATA_STORE_FILENAME)
  42. psiphon.SetEmitDiagnosticNotices(true)
  43. CLIENT_VERIFICATION_REQUIRED = true
  44. os.Exit(m.Run())
  45. }
  46. // Note: not testing fronting meek protocols, which client is
  47. // hard-wired to except running on privileged ports 80 and 443.
  48. func TestSSH(t *testing.T) {
  49. runServer(t,
  50. &runServerConfig{
  51. tunnelProtocol: "SSH",
  52. enableSSHAPIRequests: true,
  53. doHotReload: false,
  54. denyTrafficRules: false,
  55. doTunneledWebRequest: true,
  56. doTunneledNTPRequest: true,
  57. })
  58. }
  59. func TestOSSH(t *testing.T) {
  60. runServer(t,
  61. &runServerConfig{
  62. tunnelProtocol: "OSSH",
  63. enableSSHAPIRequests: true,
  64. doHotReload: false,
  65. denyTrafficRules: false,
  66. doTunneledWebRequest: true,
  67. doTunneledNTPRequest: true,
  68. })
  69. }
  70. func TestUnfrontedMeek(t *testing.T) {
  71. runServer(t,
  72. &runServerConfig{
  73. tunnelProtocol: "UNFRONTED-MEEK-OSSH",
  74. enableSSHAPIRequests: true,
  75. doHotReload: false,
  76. denyTrafficRules: false,
  77. doTunneledWebRequest: true,
  78. doTunneledNTPRequest: true,
  79. })
  80. }
  81. func TestUnfrontedMeekHTTPS(t *testing.T) {
  82. runServer(t,
  83. &runServerConfig{
  84. tunnelProtocol: "UNFRONTED-MEEK-HTTPS-OSSH",
  85. enableSSHAPIRequests: true,
  86. doHotReload: false,
  87. denyTrafficRules: false,
  88. doTunneledWebRequest: true,
  89. doTunneledNTPRequest: true,
  90. })
  91. }
  92. func TestWebTransportAPIRequests(t *testing.T) {
  93. runServer(t,
  94. &runServerConfig{
  95. tunnelProtocol: "OSSH",
  96. enableSSHAPIRequests: false,
  97. doHotReload: false,
  98. denyTrafficRules: false,
  99. doTunneledWebRequest: true,
  100. doTunneledNTPRequest: true,
  101. })
  102. }
  103. func TestHotReload(t *testing.T) {
  104. runServer(t,
  105. &runServerConfig{
  106. tunnelProtocol: "OSSH",
  107. enableSSHAPIRequests: true,
  108. doHotReload: true,
  109. denyTrafficRules: false,
  110. doTunneledWebRequest: true,
  111. doTunneledNTPRequest: true,
  112. })
  113. }
  114. func TestDenyTrafficRules(t *testing.T) {
  115. runServer(t,
  116. &runServerConfig{
  117. tunnelProtocol: "OSSH",
  118. enableSSHAPIRequests: true,
  119. doHotReload: true,
  120. denyTrafficRules: true,
  121. doTunneledWebRequest: true,
  122. doTunneledNTPRequest: true,
  123. })
  124. }
  125. func TestTCPOnlySLOK(t *testing.T) {
  126. runServer(t,
  127. &runServerConfig{
  128. tunnelProtocol: "OSSH",
  129. enableSSHAPIRequests: true,
  130. doHotReload: false,
  131. denyTrafficRules: false,
  132. doTunneledWebRequest: true,
  133. doTunneledNTPRequest: false,
  134. })
  135. }
  136. func TestUDPOnlySLOK(t *testing.T) {
  137. runServer(t,
  138. &runServerConfig{
  139. tunnelProtocol: "OSSH",
  140. enableSSHAPIRequests: true,
  141. doHotReload: false,
  142. denyTrafficRules: false,
  143. doTunneledWebRequest: false,
  144. doTunneledNTPRequest: true,
  145. })
  146. }
  147. type runServerConfig struct {
  148. tunnelProtocol string
  149. enableSSHAPIRequests bool
  150. doHotReload bool
  151. denyTrafficRules bool
  152. doTunneledWebRequest bool
  153. doTunneledNTPRequest bool
  154. }
  155. func sendNotificationReceived(c chan<- struct{}) {
  156. select {
  157. case c <- *new(struct{}):
  158. default:
  159. }
  160. }
  161. func waitOnNotification(t *testing.T, c, timeoutSignal <-chan struct{}, timeoutMessage string) {
  162. select {
  163. case <-c:
  164. case <-timeoutSignal:
  165. t.Fatalf(timeoutMessage)
  166. }
  167. }
  168. const dummyClientVerificationPayload = `
  169. {
  170. "status": 0,
  171. "payload": ""
  172. }`
  173. func runServer(t *testing.T, runConfig *runServerConfig) {
  174. // create a server
  175. var err error
  176. serverIPaddress := ""
  177. for _, interfaceName := range []string{"eth0", "en0"} {
  178. serverIPaddress, err = psiphon.GetInterfaceIPAddress(interfaceName)
  179. if err == nil {
  180. break
  181. }
  182. }
  183. if err != nil {
  184. t.Fatalf("error getting server IP address: %s", err)
  185. }
  186. serverConfigJSON, _, encodedServerEntry, err := GenerateConfig(
  187. &GenerateConfigParams{
  188. ServerIPAddress: serverIPaddress,
  189. EnableSSHAPIRequests: runConfig.enableSSHAPIRequests,
  190. WebServerPort: 8000,
  191. TunnelProtocolPorts: map[string]int{runConfig.tunnelProtocol: 4000},
  192. })
  193. if err != nil {
  194. t.Fatalf("error generating server config: %s", err)
  195. }
  196. // customize server config
  197. // Pave psinet with random values to test handshake homepages.
  198. psinetFilename := "psinet.json"
  199. sponsorID, expectedHomepageURL := pavePsinetDatabaseFile(t, psinetFilename)
  200. // Pave traffic rules file which exercises handshake parameter filtering. Client
  201. // must handshake with specified sponsor ID in order to allow ports for tunneled
  202. // requests.
  203. trafficRulesFilename := "traffic_rules.json"
  204. paveTrafficRulesFile(t, trafficRulesFilename, sponsorID, runConfig.denyTrafficRules)
  205. oslConfigFilename := "osl_config.json"
  206. propagationChannelID := paveOSLConfigFile(t, oslConfigFilename)
  207. var serverConfig interface{}
  208. json.Unmarshal(serverConfigJSON, &serverConfig)
  209. serverConfig.(map[string]interface{})["GeoIPDatabaseFilename"] = ""
  210. serverConfig.(map[string]interface{})["PsinetDatabaseFilename"] = psinetFilename
  211. serverConfig.(map[string]interface{})["TrafficRulesFilename"] = trafficRulesFilename
  212. serverConfig.(map[string]interface{})["OSLConfigFilename"] = oslConfigFilename
  213. serverConfig.(map[string]interface{})["LogLevel"] = "debug"
  214. // 1 second is the minimum period; should be small enough to emit a log during the
  215. // test run, but not guaranteed
  216. serverConfig.(map[string]interface{})["LoadMonitorPeriodSeconds"] = 1
  217. serverConfigJSON, _ = json.Marshal(serverConfig)
  218. // run server
  219. serverWaitGroup := new(sync.WaitGroup)
  220. serverWaitGroup.Add(1)
  221. go func() {
  222. defer serverWaitGroup.Done()
  223. err := RunServices(serverConfigJSON)
  224. if err != nil {
  225. // TODO: wrong goroutine for t.FatalNow()
  226. t.Fatalf("error running server: %s", err)
  227. }
  228. }()
  229. defer func() {
  230. // Test: orderly server shutdown
  231. p, _ := os.FindProcess(os.Getpid())
  232. p.Signal(os.Interrupt)
  233. shutdownTimeout := time.NewTimer(5 * time.Second)
  234. shutdownOk := make(chan struct{}, 1)
  235. go func() {
  236. serverWaitGroup.Wait()
  237. shutdownOk <- *new(struct{})
  238. }()
  239. select {
  240. case <-shutdownOk:
  241. case <-shutdownTimeout.C:
  242. t.Fatalf("server shutdown timeout exceeded")
  243. }
  244. }()
  245. // Test: hot reload (of psinet and traffic rules)
  246. if runConfig.doHotReload {
  247. // TODO: monitor logs for more robust wait-until-loaded
  248. time.Sleep(1 * time.Second)
  249. // Pave a new psinet and traffic rules with different random values.
  250. sponsorID, expectedHomepageURL = pavePsinetDatabaseFile(t, psinetFilename)
  251. paveTrafficRulesFile(t, trafficRulesFilename, sponsorID, runConfig.denyTrafficRules)
  252. p, _ := os.FindProcess(os.Getpid())
  253. p.Signal(syscall.SIGUSR1)
  254. // TODO: monitor logs for more robust wait-until-reloaded
  255. time.Sleep(1 * time.Second)
  256. // After reloading psinet, the new sponsorID/expectedHomepageURL
  257. // should be active, as tested in the client "Homepage" notice
  258. // handler below.
  259. }
  260. // connect to server with client
  261. // TODO: currently, TargetServerEntry only works with one tunnel
  262. numTunnels := 1
  263. localSOCKSProxyPort := 1081
  264. localHTTPProxyPort := 8081
  265. establishTunnelPausePeriodSeconds := 1
  266. // Note: calling LoadConfig ensures all *int config fields are initialized
  267. clientConfigJSON := `
  268. {
  269. "ClientPlatform" : "Android",
  270. "ClientVersion" : "0",
  271. "SponsorId" : "0",
  272. "PropagationChannelId" : "0"
  273. }`
  274. clientConfig, _ := psiphon.LoadConfig([]byte(clientConfigJSON))
  275. clientConfig.SponsorId = sponsorID
  276. clientConfig.PropagationChannelId = propagationChannelID
  277. clientConfig.ConnectionWorkerPoolSize = numTunnels
  278. clientConfig.TunnelPoolSize = numTunnels
  279. clientConfig.DisableRemoteServerListFetcher = true
  280. clientConfig.EstablishTunnelPausePeriodSeconds = &establishTunnelPausePeriodSeconds
  281. clientConfig.TargetServerEntry = string(encodedServerEntry)
  282. clientConfig.TunnelProtocol = runConfig.tunnelProtocol
  283. clientConfig.LocalSocksProxyPort = localSOCKSProxyPort
  284. clientConfig.LocalHttpProxyPort = localHTTPProxyPort
  285. clientConfig.ReportSLOKs = true
  286. err = psiphon.InitDataStore(clientConfig)
  287. if err != nil {
  288. t.Fatalf("error initializing client datastore: %s", err)
  289. }
  290. controller, err := psiphon.NewController(clientConfig)
  291. if err != nil {
  292. t.Fatalf("error creating client controller: %s", err)
  293. }
  294. tunnelsEstablished := make(chan struct{}, 1)
  295. homepageReceived := make(chan struct{}, 1)
  296. slokSeeded := make(chan struct{}, 1)
  297. verificationRequired := make(chan struct{}, 1)
  298. verificationCompleted := make(chan struct{}, 1)
  299. psiphon.SetNoticeOutput(psiphon.NewNoticeReceiver(
  300. func(notice []byte) {
  301. //fmt.Printf("%s\n", string(notice))
  302. noticeType, payload, err := psiphon.GetNotice(notice)
  303. if err != nil {
  304. return
  305. }
  306. switch noticeType {
  307. case "Tunnels":
  308. // Do not set verification payload until tunnel is
  309. // established. Otherwise will silently take no action.
  310. controller.SetClientVerificationPayloadForActiveTunnels("")
  311. count := int(payload["count"].(float64))
  312. if count >= numTunnels {
  313. sendNotificationReceived(tunnelsEstablished)
  314. }
  315. case "Homepage":
  316. homepageURL := payload["url"].(string)
  317. if homepageURL != expectedHomepageURL {
  318. // TODO: wrong goroutine for t.FatalNow()
  319. t.Fatalf("unexpected homepage: %s", homepageURL)
  320. }
  321. sendNotificationReceived(homepageReceived)
  322. case "SLOKSeeded":
  323. sendNotificationReceived(slokSeeded)
  324. case "ClientVerificationRequired":
  325. sendNotificationReceived(verificationRequired)
  326. controller.SetClientVerificationPayloadForActiveTunnels(dummyClientVerificationPayload)
  327. case "NoticeClientVerificationRequestCompleted":
  328. sendNotificationReceived(verificationCompleted)
  329. }
  330. }))
  331. controllerShutdownBroadcast := make(chan struct{})
  332. controllerWaitGroup := new(sync.WaitGroup)
  333. controllerWaitGroup.Add(1)
  334. go func() {
  335. defer controllerWaitGroup.Done()
  336. controller.Run(controllerShutdownBroadcast)
  337. }()
  338. stopClient := func() {
  339. close(controllerShutdownBroadcast)
  340. shutdownTimeout := time.NewTimer(20 * time.Second)
  341. shutdownOk := make(chan struct{}, 1)
  342. go func() {
  343. controllerWaitGroup.Wait()
  344. shutdownOk <- *new(struct{})
  345. }()
  346. select {
  347. case <-shutdownOk:
  348. case <-shutdownTimeout.C:
  349. t.Fatalf("controller shutdown timeout exceeded")
  350. }
  351. }
  352. // Test: tunnels must be established, and correct homepage
  353. // must be received, within 30 seconds
  354. timeoutSignal := make(chan struct{})
  355. go func() {
  356. timer := time.NewTimer(30 * time.Second)
  357. <-timer.C
  358. close(timeoutSignal)
  359. }()
  360. waitOnNotification(t, tunnelsEstablished, timeoutSignal, "tunnel establish timeout exceeded")
  361. waitOnNotification(t, homepageReceived, timeoutSignal, "homepage received timeout exceeded")
  362. waitOnNotification(t, verificationRequired, timeoutSignal, "verification required timeout exceeded")
  363. waitOnNotification(t, verificationCompleted, timeoutSignal, "verification completed timeout exceeded")
  364. if runConfig.doTunneledWebRequest {
  365. // Test: tunneled web site fetch
  366. err = makeTunneledWebRequest(t, localHTTPProxyPort)
  367. if err == nil {
  368. if runConfig.denyTrafficRules {
  369. t.Fatalf("unexpected tunneled web request success")
  370. }
  371. } else {
  372. if !runConfig.denyTrafficRules {
  373. t.Fatalf("tunneled web request failed: %s", err)
  374. }
  375. }
  376. }
  377. if runConfig.doTunneledNTPRequest {
  378. // Test: tunneled UDP packets
  379. udpgwServerAddress := serverConfig.(map[string]interface{})["UDPInterceptUdpgwServerAddress"].(string)
  380. err = makeTunneledNTPRequest(t, localSOCKSProxyPort, udpgwServerAddress)
  381. if err == nil {
  382. if runConfig.denyTrafficRules {
  383. t.Fatalf("unexpected tunneled NTP request success")
  384. }
  385. } else {
  386. if !runConfig.denyTrafficRules {
  387. t.Fatalf("tunneled NTP request failed: %s", err)
  388. }
  389. }
  390. }
  391. // Test: stop client to trigger a final status request and receive SLOK payload
  392. stopClient()
  393. if !runConfig.denyTrafficRules {
  394. waitOnNotification(t, slokSeeded, timeoutSignal, "SLOK seeded timeout exceeded")
  395. }
  396. }
  397. func makeTunneledWebRequest(t *testing.T, localHTTPProxyPort int) error {
  398. testUrl := "https://psiphon.ca"
  399. roundTripTimeout := 30 * time.Second
  400. proxyUrl, err := url.Parse(fmt.Sprintf("http://127.0.0.1:%d", localHTTPProxyPort))
  401. if err != nil {
  402. return fmt.Errorf("error initializing proxied HTTP request: %s", err)
  403. }
  404. httpClient := &http.Client{
  405. Transport: &http.Transport{
  406. Proxy: http.ProxyURL(proxyUrl),
  407. },
  408. Timeout: roundTripTimeout,
  409. }
  410. response, err := httpClient.Get(testUrl)
  411. if err != nil {
  412. return fmt.Errorf("error sending proxied HTTP request: %s", err)
  413. }
  414. _, err = ioutil.ReadAll(response.Body)
  415. if err != nil {
  416. return fmt.Errorf("error reading proxied HTTP response: %s", err)
  417. }
  418. response.Body.Close()
  419. return nil
  420. }
  421. func makeTunneledNTPRequest(t *testing.T, localSOCKSProxyPort int, udpgwServerAddress string) error {
  422. testHostname := "pool.ntp.org"
  423. timeout := 10 * time.Second
  424. localUDPProxyAddress, err := net.ResolveUDPAddr("udp", "127.0.0.1:7301")
  425. if err != nil {
  426. t.Fatalf("ResolveUDPAddr failed: %s", err)
  427. }
  428. // Note: this proxy is intended for this test only -- it only accepts a single connection,
  429. // handles it, and then terminates.
  430. localUDPProxy := func(destinationIP net.IP, destinationPort uint16, waitGroup *sync.WaitGroup) {
  431. if waitGroup != nil {
  432. defer waitGroup.Done()
  433. }
  434. destination := net.JoinHostPort(destinationIP.String(), strconv.Itoa(int(destinationPort)))
  435. serverUDPConn, err := net.ListenUDP("udp", localUDPProxyAddress)
  436. if err != nil {
  437. t.Logf("ListenUDP for %s failed: %s", destination, err)
  438. return
  439. }
  440. defer serverUDPConn.Close()
  441. udpgwPreambleSize := 11 // see writeUdpgwPreamble
  442. buffer := make([]byte, udpgwProtocolMaxMessageSize)
  443. packetSize, clientAddr, err := serverUDPConn.ReadFromUDP(
  444. buffer[udpgwPreambleSize:len(buffer)])
  445. if err != nil {
  446. t.Logf("serverUDPConn.Read for %s failed: %s", destination, err)
  447. return
  448. }
  449. socksProxyAddress := fmt.Sprintf("127.0.0.1:%d", localSOCKSProxyPort)
  450. dialer, err := proxy.SOCKS5("tcp", socksProxyAddress, nil, proxy.Direct)
  451. if err != nil {
  452. t.Logf("proxy.SOCKS5 for %s failed: %s", destination, err)
  453. return
  454. }
  455. socksTCPConn, err := dialer.Dial("tcp", udpgwServerAddress)
  456. if err != nil {
  457. t.Logf("dialer.Dial for %s failed: %s", destination, err)
  458. return
  459. }
  460. defer socksTCPConn.Close()
  461. flags := uint8(0)
  462. if destinationPort == 53 {
  463. flags = udpgwProtocolFlagDNS
  464. }
  465. err = writeUdpgwPreamble(
  466. udpgwPreambleSize,
  467. flags,
  468. 0,
  469. destinationIP,
  470. destinationPort,
  471. uint16(packetSize),
  472. buffer)
  473. if err != nil {
  474. t.Logf("writeUdpgwPreamble for %s failed: %s", destination, err)
  475. return
  476. }
  477. _, err = socksTCPConn.Write(buffer[0 : udpgwPreambleSize+packetSize])
  478. if err != nil {
  479. t.Logf("socksTCPConn.Write for %s failed: %s", destination, err)
  480. return
  481. }
  482. updgwProtocolMessage, err := readUdpgwMessage(socksTCPConn, buffer)
  483. if err != nil {
  484. t.Logf("readUdpgwMessage for %s failed: %s", destination, err)
  485. return
  486. }
  487. _, err = serverUDPConn.WriteToUDP(updgwProtocolMessage.packet, clientAddr)
  488. if err != nil {
  489. t.Logf("serverUDPConn.Write for %s failed: %s", destination, err)
  490. return
  491. }
  492. }
  493. // Tunneled DNS request
  494. waitGroup := new(sync.WaitGroup)
  495. waitGroup.Add(1)
  496. go localUDPProxy(
  497. net.IP(make([]byte, 4)), // ignored due to transparent DNS forwarding
  498. 53,
  499. waitGroup)
  500. // TODO: properly synchronize with local UDP proxy startup
  501. time.Sleep(1 * time.Second)
  502. clientUDPConn, err := net.DialUDP("udp", nil, localUDPProxyAddress)
  503. if err != nil {
  504. return fmt.Errorf("DialUDP failed: %s", err)
  505. }
  506. clientUDPConn.SetReadDeadline(time.Now().Add(timeout))
  507. clientUDPConn.SetWriteDeadline(time.Now().Add(timeout))
  508. addrs, _, err := psiphon.ResolveIP(testHostname, clientUDPConn)
  509. clientUDPConn.Close()
  510. if err == nil && (len(addrs) == 0 || len(addrs[0]) < 4) {
  511. err = errors.New("no address")
  512. }
  513. if err != nil {
  514. return fmt.Errorf("ResolveIP failed: %s", err)
  515. }
  516. waitGroup.Wait()
  517. // Tunneled NTP request
  518. go localUDPProxy(addrs[0][len(addrs[0])-4:], 123, nil)
  519. // TODO: properly synchronize with local UDP proxy startup
  520. time.Sleep(1 * time.Second)
  521. clientUDPConn, err = net.DialUDP("udp", nil, localUDPProxyAddress)
  522. if err != nil {
  523. return fmt.Errorf("DialUDP failed: %s", err)
  524. }
  525. clientUDPConn.SetReadDeadline(time.Now().Add(timeout))
  526. clientUDPConn.SetWriteDeadline(time.Now().Add(timeout))
  527. // NTP protocol code from: https://groups.google.com/d/msg/golang-nuts/FlcdMU5fkLQ/CAeoD9eqm-IJ
  528. ntpData := make([]byte, 48)
  529. ntpData[0] = 3<<3 | 3
  530. _, err = clientUDPConn.Write(ntpData)
  531. if err != nil {
  532. clientUDPConn.Close()
  533. return fmt.Errorf("NTP Write failed: %s", err)
  534. }
  535. _, err = clientUDPConn.Read(ntpData)
  536. if err != nil {
  537. clientUDPConn.Close()
  538. return fmt.Errorf("NTP Read failed: %s", err)
  539. }
  540. clientUDPConn.Close()
  541. var sec, frac uint64
  542. sec = uint64(ntpData[43]) | uint64(ntpData[42])<<8 | uint64(ntpData[41])<<16 | uint64(ntpData[40])<<24
  543. frac = uint64(ntpData[47]) | uint64(ntpData[46])<<8 | uint64(ntpData[45])<<16 | uint64(ntpData[44])<<24
  544. nsec := sec * 1e9
  545. nsec += (frac * 1e9) >> 32
  546. ntpNow := time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC).Add(time.Duration(nsec)).Local()
  547. now := time.Now()
  548. diff := ntpNow.Sub(now)
  549. if diff < 0 {
  550. diff = -diff
  551. }
  552. if diff > 1*time.Minute {
  553. return fmt.Errorf("Unexpected NTP time: %s; local time: %s", ntpNow, now)
  554. }
  555. return nil
  556. }
  557. func pavePsinetDatabaseFile(t *testing.T, psinetFilename string) (string, string) {
  558. sponsorID, _ := common.MakeRandomStringHex(8)
  559. fakeDomain, _ := common.MakeRandomStringHex(4)
  560. fakePath, _ := common.MakeRandomStringHex(4)
  561. expectedHomepageURL := fmt.Sprintf("https://%s.com/%s", fakeDomain, fakePath)
  562. psinetJSONFormat := `
  563. {
  564. "sponsors": {
  565. "%s": {
  566. "home_pages": {
  567. "None": [
  568. {
  569. "region": null,
  570. "url": "%s"
  571. }
  572. ]
  573. }
  574. }
  575. }
  576. }
  577. `
  578. psinetJSON := fmt.Sprintf(psinetJSONFormat, sponsorID, expectedHomepageURL)
  579. err := ioutil.WriteFile(psinetFilename, []byte(psinetJSON), 0600)
  580. if err != nil {
  581. t.Fatalf("error paving psinet database file: %s", err)
  582. }
  583. return sponsorID, expectedHomepageURL
  584. }
  585. func paveTrafficRulesFile(t *testing.T, trafficRulesFilename, sponsorID string, deny bool) {
  586. allowTCPPorts := "443"
  587. allowUDPPorts := "53, 123"
  588. if deny {
  589. allowTCPPorts = "0"
  590. allowUDPPorts = "0"
  591. }
  592. trafficRulesJSONFormat := `
  593. {
  594. "DefaultRules" : {
  595. "RateLimits" : {
  596. "ReadBytesPerSecond": 16384,
  597. "WriteBytesPerSecond": 16384
  598. },
  599. "AllowTCPPorts" : [0],
  600. "AllowUDPPorts" : [0]
  601. },
  602. "FilteredRules" : [
  603. {
  604. "Filter" : {
  605. "HandshakeParameters" : {
  606. "sponsor_id" : ["%s"]
  607. }
  608. },
  609. "Rules" : {
  610. "RateLimits" : {
  611. "ReadUnthrottledBytes": 132352,
  612. "WriteUnthrottledBytes": 132352
  613. },
  614. "AllowTCPPorts" : [%s],
  615. "AllowUDPPorts" : [%s]
  616. }
  617. }
  618. ]
  619. }
  620. `
  621. trafficRulesJSON := fmt.Sprintf(
  622. trafficRulesJSONFormat, sponsorID, allowTCPPorts, allowUDPPorts)
  623. err := ioutil.WriteFile(trafficRulesFilename, []byte(trafficRulesJSON), 0600)
  624. if err != nil {
  625. t.Fatalf("error paving traffic rules file: %s", err)
  626. }
  627. }
  628. func paveOSLConfigFile(t *testing.T, oslConfigFilename string) string {
  629. oslConfigJSONFormat := `
  630. {
  631. "Schemes" : [
  632. {
  633. "Epoch" : "%s",
  634. "Regions" : [],
  635. "PropagationChannelIDs" : ["%s"],
  636. "MasterKey" : "wFuSbqU/pJ/35vRmoM8T9ys1PgDa8uzJps1Y+FNKa5U=",
  637. "SeedSpecs" : [
  638. {
  639. "ID" : "IXHWfVgWFkEKvgqsjmnJuN3FpaGuCzQMETya+DSQvsk=",
  640. "UpstreamSubnets" : ["0.0.0.0/0"],
  641. "Targets" :
  642. {
  643. "BytesRead" : 1,
  644. "BytesWritten" : 1,
  645. "PortForwardDurationNanoseconds" : 1
  646. }
  647. },
  648. {
  649. "ID" : "qvpIcORLE2Pi5TZmqRtVkEp+OKov0MhfsYPLNV7FYtI=",
  650. "UpstreamSubnets" : ["0.0.0.0/0"],
  651. "Targets" :
  652. {
  653. "BytesRead" : 1,
  654. "BytesWritten" : 1,
  655. "PortForwardDurationNanoseconds" : 1
  656. }
  657. }
  658. ],
  659. "SeedSpecThreshold" : 2,
  660. "SeedPeriodNanoseconds" : 10000000000,
  661. "SeedPeriodKeySplits": [
  662. {
  663. "Total": 2,
  664. "Threshold": 2
  665. }
  666. ]
  667. }
  668. ]
  669. }
  670. `
  671. propagationChannelID, _ := common.MakeRandomStringHex(8)
  672. now := time.Now().UTC()
  673. epoch := now.Truncate(10 * time.Second)
  674. epochStr := epoch.Format(time.RFC3339Nano)
  675. oslConfigJSON := fmt.Sprintf(
  676. oslConfigJSONFormat, epochStr, propagationChannelID)
  677. err := ioutil.WriteFile(oslConfigFilename, []byte(oslConfigJSON), 0600)
  678. if err != nil {
  679. t.Fatalf("error paving osl config file: %s", err)
  680. }
  681. return propagationChannelID
  682. }