├── .DS_Store ├── .github ├── dependabot.yml └── workflows │ └── docker-image.yml ├── Dockerfile ├── LICENSE.md ├── README.md ├── docker-compose.yaml ├── images └── Firefox-Proxy-Settings.png ├── nginx ├── nginx_allowlist.conf ├── nginx_denylist.conf └── sources.list /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reiz/nginx_proxy/193e18714b5699fc4bef3cb3568a5fa489966a3d/.DS_Store -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | -------------------------------------------------------------------------------- /.github/workflows/docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Test - Container Image Build 2 | 3 | on: 4 | push: 5 | branches: [master,develop] 6 | pull_request: 7 | branches: [master,develop] 8 | 9 | jobs: 10 | build-and-test: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | 16 | - name: Set up Docker Buildx 17 | uses: docker/setup-buildx-action@v3 18 | 19 | - name: Build 20 | uses: docker/build-push-action@v6 21 | with: 22 | context: . 23 | load: true 24 | tags: nginx_proxy:latest 25 | cache-from: type=gha 26 | cache-to: type=gha,mode=max 27 | 28 | - name: Test with curl 29 | run: | 30 | set +e 31 | docker images -a 32 | docker run -d --name nginx_proxy nginx_proxy:latest 33 | sleep 5 34 | nginx_proxy_ip=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx_proxy) 35 | err=1 36 | count=0 37 | while [[ $err != 0 ]]; do 38 | curl https://www.google.com -svo /dev/null -x $nginx_proxy_ip:8888 39 | err=$? 40 | [[ $err == 0 ]] && exit 0 41 | count=$(( count + 1 )) 42 | [[ $count -ge 5 ]] && exit 1 43 | done 44 | 45 | - name: Stop containers and show logs 46 | if: always() 47 | run: | 48 | docker exec -i nginx_proxy cat /var/log/nginx_errors.log || true 49 | docker exec -i nginx_proxy cat /var/log/nginx_access.log || true 50 | docker rm -f nginx_proxy || true 51 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMAGE=ubuntu:20.04 2 | FROM $IMAGE as builder 3 | 4 | COPY sources.list /etc/apt/sources.list 5 | ADD https://github.com/krallin/tini/releases/download/v0.19.0/tini /tini 6 | 7 | WORKDIR /app 8 | 9 | RUN apt-get update && \ 10 | apt-get install -y libfontconfig1 libpcre3 libpcre3-dev git dpkg-dev libpng-dev libssl-dev && \ 11 | apt-get source nginx && \ 12 | git clone https://github.com/chobits/ngx_http_proxy_connect_module && \ 13 | cd /app/nginx-* && \ 14 | patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_1018.patch && \ 15 | cd /app/nginx-* && \ 16 | ./configure --add-module=/app/ngx_http_proxy_connect_module --with-http_ssl_module \ 17 | --with-http_stub_status_module --with-http_realip_module --with-threads && \ 18 | make -j$(grep processor /proc/cpuinfo | wc -l) && \ 19 | make install -j$(grep processor /proc/cpuinfo | wc -l) && \ 20 | chmod +x /tini 21 | 22 | FROM $IMAGE 23 | 24 | LABEL maintainer='Robert Reiz ' 25 | 26 | COPY nginx_allowlist.conf /usr/local/nginx/conf/nginx.conf 27 | COPY --from=builder /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx 28 | COPY --from=builder /tini /tini 29 | ## save apt-get update step 30 | COPY --from=builder /var/lib/apt/lists/ /var/lib/apt/lists/ 31 | 32 | RUN apt-get install -y --no-install-recommends libssl-dev && \ 33 | mkdir -p /usr/local/nginx/logs/ && \ 34 | touch /usr/local/nginx/logs/error.log && \ 35 | apt-get clean autoclean && \ 36 | apt-get autoremove --yes && \ 37 | rm -rf /var/lib/{apt,dpkg,cache,log}/ 38 | 39 | EXPOSE 8888 40 | 41 | ENTRYPOINT ["/tini", "--"] 42 | 43 | CMD ["/usr/local/nginx/sbin/nginx"] 44 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Robert Reiz 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nginx forward proxy 2 | 3 | [Nginx](https://nginx.org/en/) is a very fast HTTP and reverse proxy server. 4 | Usually, Nginx is used to serve and cache static assets or as proxy or load balancer for incoming traffic to application servers. In this repository, it is used as forward proxy. 5 | 6 | ## Use Case 7 | 8 | Assume you have a network where you want to control outgoing traffic. 9 | You either want to: 10 | 11 | - Deny all outgoing calls by default and only allow HTTP(S) calls to allowlisted URLs. 12 | - Allow all outgoing calls by default and only block HTTP(S) calls to denylisted URLs. 13 | 14 | The Docker daemon can be configured that way that it routes all traffic through an proxy. This proxy can be an Nginx which is configured as forwarding proxying. 15 | 16 | ## ngx\_http\_proxy\_connect\_module 17 | 18 | Nginx can be configured for forwarding proxying. 19 | Unfortunately, that doesn't work very well with HTTPS connections. 20 | As soon the user is calling a URL via https, Nginx will throw errors. 21 | There is a [StackOverflow issue](https://superuser.com/questions/604352/nginx-as-forward-proxy-for-https) 22 | to that topic. Luckily there is a solution for that problem. 23 | The [ngx\_http\_proxy\_connect\_module](https://github.com/chobits/ngx_http_proxy_connect_module) 24 | is solving this issue. If Nginx is compiled with that module, 25 | the proxying will work with SSL connections as well. 26 | 27 | ## Docker Build 28 | 29 | The Dockerfile in this repository is assembling an Nginx with the [ngx\_http\_proxy\_connect\_module](https://github.com/chobits/ngx_http_proxy_connect_module) 30 | and an nginx.conf file which blocks all outgoing traffic by default, 31 | but allows access to some allowlisted domains like google.com. 32 | The Docker image can be built like this: 33 | 34 | ``` 35 | docker build -t reiz/nginx_proxy:0.0.3 . 36 | ``` 37 | 38 | Or simply download it from [Docker Hub](https://hub.docker.com/r/reiz/nginx_proxy/) with: 39 | 40 | ``` 41 | docker pull reiz/nginx_proxy:0.0.3 42 | ``` 43 | 44 | ## Allowlist certain domains 45 | 46 | This repository contains two nginx configuration files. 47 | The `nginx_allowlist.conf` file is built for the use case that you want to deny all outgoing traffic by default and only allow some allowlisted domains. 48 | In the first server section domains can be allowlisted by simply adding a 49 | `server_name *` line for each allowlisted domain. Here an example: 50 | 51 | ``` 52 | # Allowlist Google 53 | server { 54 | listen 8888; 55 | server_name google.com; 56 | server_name *.google.com; 57 | server_name google.de; 58 | server_name www.google.de; 59 | proxy_connect; 60 | proxy_max_temp_file_size 0; 61 | resolver 8.8.8.8; 62 | location / { 63 | proxy_pass http://$http_host; 64 | proxy_set_header Host $http_host; 65 | } 66 | } 67 | ``` 68 | 69 | Regex can be used to describe a domain. This `*.google.com` for example is allowlisting all subdomains of google.com. In the above example, google.com and all subdomains of it are allowlisted. Beside that google.de and www.google.de are allowlisted. Subdomains of google.de are **not** allowlisted. 70 | The proxy would allow outgoing calls to this domains: 71 | 72 | - google.com 73 | - www.google.com 74 | - mail.google.com 75 | - api.google.com 76 | - google.de 77 | - www.google.de 78 | 79 | This domains are blocked with the above configuration: 80 | 81 | - mail.google.de 82 | - api.google.de 83 | 84 | By starting the Docker container the file can be mounted into the running container. 85 | 86 | ``` 87 | docker run -d -p 8888:8888 -v ${PWD}/nginx_allowlist.conf:/usr/local/nginx/conf/nginx.conf reiz/nginx_proxy:0.0.3 88 | ``` 89 | 90 | Now the Docker container is running with the mounted configuration. 91 | 92 | ## Denylist certain domains 93 | 94 | This repository contains two nginx configuration files. 95 | The `nginx_denylist.conf` file is built for the use case that you want to allow all outgoing traffic by default and only block traffic to some domains. 96 | In the first server section domains can be denylisted by simply adding a 97 | `server_name *` line for each denylisted domain. Here an example: 98 | 99 | ``` 100 | server { 101 | listen 8888; 102 | server_name google.com; 103 | server_name *.google.com; 104 | return 404; 105 | } 106 | ``` 107 | 108 | In the example above all pages would be accessible, but google.com and all subdomains of it would be blocked. Regex can be used here in the same way as in the allowlist example. 109 | By starting the Docker container the file can be mounted into the running container. 110 | 111 | ``` 112 | docker run -d -p 8888:8888 -v ${PWD}/nginx_denylist.conf:/usr/local/nginx/conf/nginx.conf reiz/nginx_proxy:0.0.3 113 | ``` 114 | 115 | Now the Docker container is running with the mounted configuration. 116 | 117 | ## Testing 118 | 119 | You can test your configuration by pointing your Browser to the Nginx proxy in the running Docker container. 120 | If you run the Docker container on your localhost, then you can point your Browser to `localhost:8888`. 121 | Here is an example how it looks like in Firefox: 122 | 123 | ![Firefox Proxy Settings](images/Firefox-Proxy-Settings.png) 124 | 125 | ## Configuring Docker and Kubernetes with a Proxy 126 | 127 | Assuming you have a cluster of Docker machines (Kubernetes cluster) 128 | and you would like to route all outgoing traffic to your proxy. 129 | That can be achieved by setting some global ENV variables on each Docker machine. 130 | 131 | For RedHat/CentOS version 6: 132 | 133 | ```shell 134 | cat < 138 | EOF 139 | 140 | sudo service docker restart 141 | ``` 142 | 143 | For RedHat/CentOS version 7, remove export: 144 | 145 | ```shell 146 | cat < 150 | EOF 151 | 152 | sudo sed -i '/\[Service\]/a EnvironmentFile=/etc/sysconfig/docker' /usr/lib/systemd/system/docker.service 153 | sudo systemctl daemon-reload 154 | sudo service docker restart 155 | ``` 156 | 157 | For Ubuntu 14.04: 158 | 159 | ```shell 160 | cat < 164 | EOF 165 | 166 | sudo restart docker 167 | ``` 168 | 169 | For Kubernetes it works the same way. 170 | The `http_proxy` ENV has to be set before the K8S processes are starting. 171 | Minikube can be started with proxy params directly. 172 | Here an example: 173 | 174 | ```shell 175 | https_proxy=http://:80 minikube start --docker-env HTTP_PROXY=http://:80 --docker-env HTTPS_PROXY=http://:80 --docker-env NO_PROXY=192.168.99.0/24 176 | ``` 177 | 178 | Alternatively the Proxy can be set by Container start as well: 179 | 180 | ```shell 181 | docker run -e "http_proxy=http://myproxy.example.com:8888" \ 182 | -e "https_proxy=https://myproxy.example.com:8888" \ 183 | -d liveperson\app run.sh 184 | ``` 185 | 186 | ## Version Matrix 187 | 188 | This tables show which Docker tag contains which Ubuntu & Nginx version: 189 | 190 | | Docker tag | Ubuntu version | Nginx version | Published at | Comment | 191 | |-------------------------|----------------|---------------|--------------|-----------------| 192 | | reiz/nginx_proxy:0.0.1 | 16.04 | 1.10.3 | | | 193 | | reiz/nginx_proxy:0.0.2 | 18.04 | 1.14.0 | | | 194 | | reiz/nginx_proxy:0.0.3 | 20.04 | 1.18.0 | | | 195 | | reiz/nginx_proxy:0.0.4 | 20.04 | 1.18.0 | 2021-04-25 | With libssl-dev | 196 | | reiz/nginx_proxy:0.0.5 | 20.04 | 1.18.0 | 2021-09-17 | Reduced image size from 471MB to 147MB | 197 | 198 | 199 | ## License 200 | 201 | This repository is open source under the MIT license. The full license text is available in the LICENSE.md file. 202 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | nginx_proxy: 4 | image: nginx_proxy:latest 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | container_name: nginx_proxy 9 | volumes: 10 | - ./nginx_allowlist.conf:/usr/local/nginx/conf/nginx.conf 11 | environment: 12 | - TZ=Etc/UTC 13 | restart: always 14 | -------------------------------------------------------------------------------- /images/Firefox-Proxy-Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reiz/nginx_proxy/193e18714b5699fc4bef3cb3568a5fa489966a3d/images/Firefox-Proxy-Settings.png -------------------------------------------------------------------------------- /nginx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reiz/nginx_proxy/193e18714b5699fc4bef3cb3568a5fa489966a3d/nginx -------------------------------------------------------------------------------- /nginx_allowlist.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | daemon off; # Don't run Nginx as daemon, as we run it in Docker we need a foreground process. 4 | events { } 5 | 6 | http { 7 | server_names_hash_bucket_size 128; 8 | 9 | access_log /var/log/nginx_access.log; 10 | error_log /var/log/nginx_errors.log; 11 | 12 | # Allowlist Google and Heise 13 | server { 14 | listen 8888; 15 | server_name google.com; 16 | server_name *.google.com; 17 | server_name google.de; 18 | server_name *.google.de; 19 | server_name heise.de; 20 | server_name www.heise.de; 21 | proxy_connect; 22 | proxy_max_temp_file_size 0; 23 | resolver 8.8.8.8; 24 | location / { 25 | proxy_pass http://$http_host; 26 | proxy_set_header Host $http_host; 27 | } 28 | } 29 | 30 | # Everything else is denied 31 | server { 32 | listen 8888; 33 | server_name ~.+; 34 | return 404; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /nginx_denylist.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | daemon off; # Don't run Nginx as daemon, as we run it in Docker we need a foreground process. 4 | events { } 5 | 6 | http { 7 | server_names_hash_bucket_size 128; 8 | 9 | access_log /var/log/nginx_access.log; 10 | error_log /var/log/nginx_errors.log; 11 | 12 | # Denylist Google 13 | server { 14 | listen 8888; 15 | server_name google.com; 16 | server_name *.google.com; 17 | return 404; 18 | } 19 | 20 | # Everything else is allowed 21 | server { 22 | listen 8888; 23 | server_name ~.+; 24 | proxy_connect; 25 | proxy_max_temp_file_size 0; 26 | resolver 8.8.8.8; 27 | location / { 28 | proxy_pass http://$http_host; 29 | proxy_set_header Host $http_host; 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /sources.list: -------------------------------------------------------------------------------- 1 | deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse 2 | deb-src http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse 3 | 4 | deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse 5 | deb-src http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse 6 | 7 | deb http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse 8 | deb-src http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse 9 | 10 | deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse 11 | deb-src http://archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse 12 | 13 | deb http://archive.canonical.com/ubuntu focal partner 14 | deb-src http://archive.canonical.com/ubuntu focal partner 15 | --------------------------------------------------------------------------------