1import ./make-test-python.nix (
2 { lib, pkgs, ... }:
3
4 let
5 # Note: For some reason Privoxy can't issue valid
6 # certificates if the CA is generated using gnutls :(
7 certs = pkgs.runCommand "example-certs" { buildInputs = [ pkgs.openssl ]; } ''
8 mkdir $out
9
10 # generate CA keypair
11 openssl req -new -nodes -x509 \
12 -extensions v3_ca -keyout $out/ca.key \
13 -out $out/ca.crt -days 365 \
14 -subj "/O=Privoxy CA/CN=Privoxy CA"
15
16 # generate server key/signing request
17 openssl genrsa -out $out/server.key 3072
18 openssl req -new -key $out/server.key \
19 -out server.csr -sha256 \
20 -subj "/O=An unhappy server./CN=example.com"
21
22 # sign the request/generate the certificate
23 openssl x509 -req -in server.csr -CA $out/ca.crt \
24 -CAkey $out/ca.key -CAcreateserial -out $out/server.crt \
25 -days 500 -sha256
26 '';
27 in
28
29 {
30 name = "privoxy";
31 meta = with lib.maintainers; {
32 maintainers = [ rnhmjoj ];
33 };
34
35 nodes.machine =
36 { ... }:
37 {
38 services.nginx.enable = true;
39 services.nginx.virtualHosts."example.com" = {
40 addSSL = true;
41 sslCertificate = "${certs}/server.crt";
42 sslCertificateKey = "${certs}/server.key";
43 locations."/".root = pkgs.writeTextFile {
44 name = "bad-day";
45 destination = "/how-are-you/index.html";
46 text = "I've had a bad day!\n";
47 };
48 locations."/ads".extraConfig = ''
49 return 200 "Hot Nixpkgs PRs in your area. Click here!\n";
50 '';
51 };
52
53 services.privoxy = {
54 enable = true;
55 inspectHttps = true;
56 settings = {
57 ca-cert-file = "${certs}/ca.crt";
58 ca-key-file = "${certs}/ca.key";
59 debug = 65536;
60 };
61 userActions = ''
62 {+filter{positive}}
63 example.com
64
65 {+block{Fake ads}}
66 example.com/ads
67 '';
68 userFilters = ''
69 FILTER: positive This is a filter example.
70 s/bad/great/ig
71 '';
72 };
73
74 security.pki.certificateFiles = [ "${certs}/ca.crt" ];
75
76 networking.hosts."::1" = [ "example.com" ];
77 networking.proxy.httpProxy = "http://localhost:8118";
78 networking.proxy.httpsProxy = "http://localhost:8118";
79 };
80
81 nodes.machine_socks4 =
82 { ... }:
83 {
84 services.privoxy = {
85 enable = true;
86 settings.forward-socks4 = "/ 127.0.0.1:9050 .";
87 };
88 };
89 nodes.machine_socks4a =
90 { ... }:
91 {
92 services.privoxy = {
93 enable = true;
94 settings.forward-socks4a = "/ 127.0.0.1:9050 .";
95 };
96 };
97 nodes.machine_socks5 =
98 { ... }:
99 {
100 services.privoxy = {
101 enable = true;
102 settings.forward-socks5 = "/ 127.0.0.1:9050 .";
103 };
104 };
105 nodes.machine_socks5t =
106 { ... }:
107 {
108 services.privoxy = {
109 enable = true;
110 settings.forward-socks5t = "/ 127.0.0.1:9050 .";
111 };
112 };
113
114 testScript = ''
115 with subtest("Privoxy is running"):
116 machine.wait_for_unit("privoxy")
117 machine.wait_for_open_port(8118)
118 machine.succeed("curl -f http://config.privoxy.org")
119
120 with subtest("Privoxy can filter http requests"):
121 machine.wait_for_open_port(80)
122 assert "great day" in machine.succeed(
123 "curl -sfL http://example.com/how-are-you? | tee /dev/stderr"
124 )
125
126 with subtest("Privoxy can filter https requests"):
127 machine.wait_for_open_port(443)
128 assert "great day" in machine.succeed(
129 "curl -sfL https://example.com/how-are-you? | tee /dev/stderr"
130 )
131
132 with subtest("Blocks are working"):
133 machine.wait_for_open_port(443)
134 machine.fail("curl -f https://example.com/ads 1>&2")
135 machine.succeed("curl -f https://example.com/PRIVOXY-FORCE/ads 1>&2")
136
137 with subtest("Temporary certificates are cleaned"):
138 # Count current certificates
139 machine.succeed("test $(ls /run/privoxy/certs | wc -l) -gt 0")
140 # Forward in time 12 days, trigger the timer..
141 machine.succeed("date -s \"$(date --date '12 days')\"")
142 machine.systemctl("start systemd-tmpfiles-clean")
143 # ...and count again
144 machine.succeed("test $(ls /run/privoxy/certs | wc -l) -eq 0")
145
146 with subtest("Privoxy supports socks upstream proxies"):
147 for m in [machine_socks4, machine_socks4a, machine_socks5, machine_socks5t]:
148 m.wait_for_unit("privoxy")
149 m.wait_for_open_port(8118)
150 # We expect a 503 error because the dummy upstream proxy is not reachable.
151 # In issue #265654, instead privoxy segfaulted causing curl to exit with "Empty reply from server".
152 m.succeed("http_proxy=http://localhost:8118 curl -v http://does-not-exist/ 2>&1 | grep 'HTTP/1.1 503'")
153 '';
154 }
155)