import 'package:halkyon_base_server/base.dart'; import 'package:test/test.dart'; void main() { group('The proxies the operator trusts (TRUSTED_PROXIES)', () { test('are none where unset or empty', () { expect(trustedProxiesFrom(null), isEmpty); expect(trustedProxiesFrom(''), isEmpty); expect(trustedProxiesFrom(' '), isEmpty); }); test('are IP addresses, separated by commas or spaces', () { expect(trustedProxiesFrom('172.30.80.2'), {'172.30.80.2'}); expect(trustedProxiesFrom(' 172.30.80.2, 2001:db8::2 10.0.0.1 '), { '172.30.80.2', '2001:db8::2', '10.0.0.1', }); }); test('take an IPv4 address written as IPv6 as the IPv4 address', () { expect(trustedProxiesFrom('::ffff:172.30.80.2'), {'172.30.80.2'}); }); test('stop the server for anything but addresses', () { expect(() => trustedProxiesFrom('caddy'), throwsStateError); expect(() => trustedProxiesFrom('172.30.80.0/24'), throwsStateError); expect( () => trustedProxiesFrom('172.30.80.2, 300.1.1.1'), throwsStateError, ); }); }); group("A request's network", () { const caddy = {'172.30.80.2'}; test("is the connection's address where no proxy is trusted, whatever " 'X-Forwarded-For says', () { expect( visitorAddress( socket: '203.0.113.9', forwardedFor: ['198.51.100.7'], trustedProxies: const {}, ), '203.0.113.9', ); }); test('is the last address of X-Forwarded-For, the one the trusted proxy ' 'saw itself, for a connection from that proxy', () { expect( visitorAddress( socket: '172.30.80.2', forwardedFor: ['198.51.100.7'], trustedProxies: caddy, ), '198.51.100.7', ); // What a visitor sent along is in front of it, never believed. expect( visitorAddress( socket: '172.30.80.2', forwardedFor: ['10.9.9.9, 192.0.2.1 , 198.51.100.7'], trustedProxies: caddy, ), '198.51.100.7', ); expect( visitorAddress( socket: '172.30.80.2', forwardedFor: ['10.9.9.9', '2001:db8::7'], trustedProxies: caddy, ), '2001:db8::7', ); }); test('is never X-Forwarded-For from a connection the operator trusts ' 'not', () { expect( visitorAddress( socket: '203.0.113.9', forwardedFor: ['198.51.100.7'], trustedProxies: caddy, ), '203.0.113.9', ); }); test("knows the proxy by its IPv4 address on the server's IPv6 socket", () { expect( visitorAddress( socket: '::ffff:172.30.80.2', forwardedFor: ['::ffff:198.51.100.7'], trustedProxies: caddy, ), '198.51.100.7', ); }); test("is the proxy's own address where its header is missing or no " 'address', () { for (final header in [ null, [], [''], ['198.51.100.7, '], ['unknown'], ['198.51.100.7:4711'], ['[2001:db8::7]'], ]) { expect( visitorAddress( socket: '172.30.80.2', forwardedFor: header, trustedProxies: caddy, ), '172.30.80.2', reason: '$header', ); } }); test("is an IPv6 visitor's /64, as one household or server holds a " 'whole /64 and could turn through its addresses past every limit; ' 'an IPv4 visitor its address', () { expect( networkKeyOf('2001:db8:1:2:aaaa:bbbb:cccc:1'), '2001:db8:1:2::/64', ); expect( networkKeyOf('2001:db8:1:2::ffff'), networkKeyOf('2001:db8:1:2:9::1'), ); expect( networkKeyOf('2001:db8:1:3::1'), isNot(networkKeyOf('2001:db8:1:2::1')), ); expect(networkKeyOf('198.51.100.7'), '198.51.100.7'); expect(networkKeyOf(null), 'null'); }); test('is none without a connection (tests, future calls)', () { expect( visitorAddress( socket: null, forwardedFor: ['198.51.100.7'], trustedProxies: caddy, ), isNull, ); }); }); }