arblant
firefox-vpn-client / core / internal / proxy / loop_test.go
loop_test.go69 lines · 2.2 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
package proxy

import (
	"net"
	"testing"
	"time"

	"github.com/armanlife/firefox-vpn-client/core/internal/egress"
)

// One own address coming back is chance; two different ones within the
// window are a loop, warned of once a minute.
func TestLoopWatchNeedsTwoOwnAddresses(t *testing.T) {
	t.Parallel()

	var w loopWatch
	now := time.Unix(1000, 0)
	if loop, _ := w.note("1.1.1.1:443", now); loop {
		t.Fatal("one address made a loop")
	}
	if loop, _ := w.note("1.1.1.1:443", now.Add(time.Second)); loop {
		t.Fatal("the same address again made a loop")
	}
	if loop, warn := w.note("8.8.8.8:443", now.Add(2*time.Second)); !loop || !warn {
		t.Fatalf("two addresses: loop %t, warn %t", loop, warn)
	}
	if loop, warn := w.note("9.9.9.9:443", now.Add(3*time.Second)); !loop || warn {
		t.Fatalf("again within a minute: loop %t, warn %t", loop, warn)
	}
	later := now.Add(loopWindow + 10*time.Second)
	if loop, _ := w.note("1.1.1.1:443", later); loop {
		t.Fatal("old addresses still counted")
	}
}

// This program's own connections coming back through a client make a
// notice for the dashboard.
func TestALoopMakesANotice(t *testing.T) {
	loops = loopWatch{}
	t.Cleanup(func() { loops = loopWatch{} })
	for _, own := range []string{"203.0.113.21:443", "203.0.113.22:443"} {
		if err := egress.Dialer(0).Control("tcp4", own, nil); err != nil {
			t.Fatal(err)
		}
	}
	s := &SOCKSServer{upstream: &recordingOpener{}, Notices: &Notices{}}
	client, other := net.Pipe()
	defer client.Close()
	defer other.Close()
	for _, target := range []string{"203.0.113.21:443", "203.0.113.22:443"} {
		_, _ = s.openTarget(client, target, "127.0.0.1:40000")
	}
	notices := s.Notices.Since(time.Time{})
	if len(notices) != 1 || notices[0].Kind != NoticeLoop || notices[0].Count != 1 {
		t.Fatalf("notices %+v", notices)
	}
	// A client's connection to an address this program never used is no
	// loop.
	loops = loopWatch{}
	s2 := &SOCKSServer{upstream: &recordingOpener{}, Notices: &Notices{}}
	for _, target := range []string{"198.51.100.1:443", "198.51.100.2:443"} {
		_, _ = s2.openTarget(client, target, "127.0.0.1:40000")
	}
	for _, n := range s2.Notices.Since(time.Time{}) {
		if n.Kind == NoticeLoop {
			t.Fatalf("a loop without own connections: %+v", n)
		}
	}
}