Feature: BOUNCER_HOST_OVERRIDE

This commit is contained in:
Greyscale 2024-01-25 11:41:42 +01:00
parent 4d9099f488
commit 30f9ebec78
No known key found for this signature in database
GPG key ID: 74BAFF55434DA4B2
5 changed files with 53 additions and 14 deletions

View file

@ -1,6 +1,9 @@
FROM benzine/php:cli-8.1 as bouncer
ARG BUILD_DATE
ARG GIT_SHA
ENV GIT_SHA=${GIT_SHA}
ENV BUILD_DATE=${BUILD_DATE} \
GIT_SHA=${GIT_SHA}
LABEL maintainer="Matthew Baggett <matthew@baggett.me>" \
org.label-schema.vcs-url="https://github.com/benzine-framework/docker" \
org.opencontainers.image.source="https://github.com/benzine-framework/docker"

View file

@ -6,6 +6,7 @@ fix: php-cs-fixer
build-n-push:
docker build \
--build-arg BUILD_DATE=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ") \
--build-arg GIT_SHA=$(shell git rev-parse HEAD) \
--tag benzine/bouncer \
--tag ghcr.io/benzine-framework/bouncer \

View file

@ -30,7 +30,11 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
{% if hasHostOverride %}
proxy_set_header Host {{ hostOverride }};
{% else %}
proxy_set_header Host $host;
{% endif %}
{% if hasAuth %}
auth_basic "closed site";
@ -51,7 +55,7 @@ server {
{% endif %}
proxy_pass {{ targetPath }};
}
%}
}
{% if not allowNonSSL %}

View file

@ -34,16 +34,17 @@ These should not be confused.
### Served Instance Configuration
These environment variables need to be applied to the CONSUMING SERVICE and not the loadbalancer container itself.
| Key | Example | Behaviour |
|--------------------------------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|
| BOUNCER_DOMAIN | "a.example.com" | The domain that should be directed to this container |
| BOUNCER_AUTH | "username:password" e.g "root:toor" | Add a HTTP BASIC auth requirement to this hostname. |
| BOUNCER_LETSENCRYPT | Values are "yes" or "true", anything else is false | To enable, or disable Lets Encrypt service for this hostname |
| BOUNCER_TARGET_PORT | 9000 | Explicitly define the port you want to hit the service on, in case of ambiguity |
| BOUNCER_ALLOW_NON_SSL | Defaults to enabled. Values are "yes" or "true", anything else is false | Should HTTP only traffic be allowed to hit this service? If disabled, http traffic is forwarded towards https |
| BOUNCER_ALLOW_WEBSOCKETS | Defaults to enabled. Values are "yes" or "true", anything else is false | Enable websocket behaviour |
| BOUNCER_ALLOW_LARGE_PAYLOADS | Defaults to disabled. | Allows overriding the default nginx payload size. Related to BOUNCER_MAX_PAYLOADS_MEGABYTES |
| BOUNCER_MAX_PAYLOADS_MEGABYTES | numbers | Size of max payload to allow, in megabytes. Requires BOUNCER_ALLOW_LARGE_PAYLOADS to be enabled |
| Key | Example | Behaviour |
|--------------------------------|-------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| BOUNCER_DOMAIN | "a.example.com" | The domain that should be directed to this container |
| BOUNCER_AUTH | "username:password" e.g "root:toor" | Add a HTTP BASIC auth requirement to this hostname. |
| BOUNCER_HOST_OVERRIDE | "localhost:80" | Override the host header that is sent to the service. Useful for services that are not aware of their own hostname, or annoying things like [mitmproxy](https://github.com/mitmproxy/mitmproxy/issues/3234) |
| BOUNCER_LETSENCRYPT | Values are "yes" or "true", anything else is false | To enable, or disable Lets Encrypt service for this hostname |
| BOUNCER_TARGET_PORT | 9000 | Explicitly define the port you want to hit the service on, in case of ambiguity |
| BOUNCER_ALLOW_NON_SSL | Defaults to enabled. Values are "yes" or "true", anything else is false | Should HTTP only traffic be allowed to hit this service? If disabled, http traffic is forwarded towards https |
| BOUNCER_ALLOW_WEBSOCKETS | Defaults to enabled. Values are "yes" or "true", anything else is false | Enable websocket behaviour |
| BOUNCER_ALLOW_LARGE_PAYLOADS | Defaults to disabled. | Allows overriding the default nginx payload size. Related to BOUNCER_MAX_PAYLOADS_MEGABYTES |
| BOUNCER_MAX_PAYLOADS_MEGABYTES | numbers | Size of max payload to allow, in megabytes. Requires BOUNCER_ALLOW_LARGE_PAYLOADS to be enabled |
## Security considerations
If you're putting this behind access control to the docker socket, it will need access to the /swarm /services and /containers endpoints of the docker api.

View file

@ -6,6 +6,7 @@ use AdamBrett\ShellWrapper\Command\Builder as CommandBuilder;
use AdamBrett\ShellWrapper\Runners\Exec;
use Aws\S3\S3Client;
use Bramus\Monolog\Formatter\ColoredLineFormatter;
use Carbon\Carbon;
use GuzzleHttp\Client as Guzzle;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ServerException;
@ -39,6 +40,8 @@ class BouncerTarget
private ?string $username = null;
private ?string $password = null;
private ?string $hostOverride = null;
public function __construct(
private Logger $logger
) {
@ -60,9 +63,28 @@ class BouncerTarget
'proxyTimeoutSeconds' => $this->getProxyTimeoutSeconds(),
'hasAuth' => $this->hasAuth(),
'authFile' => $this->getAuthFileName(),
'hasHostOverride' => $this->hasHostOverride(),
'hostOverride' => $this->getHostOverride(),
];
}
public function getHostOverride(): ?string
{
return $this->hostOverride;
}
public function hasHostOverride(): bool
{
return $this->hostOverride !== null;
}
public function setHostOverride(string $hostOverride): BouncerTarget
{
$this->hostOverride = $hostOverride;
return $this;
}
public function getUsername(): ?string
{
return $this->username;
@ -592,12 +614,15 @@ class Bouncer
public function run(): void
{
$gitHash = substr($this->environment['GIT_SHA'], 0, 7);
$this->logger->info(sprintf('%s Starting Bouncer git=%s...', Emoji::CHARACTER_TIMER_CLOCK, $gitHash));
$this->logger->info('{emoji} Starting Bouncer git={git_sha}...', ['emoji' => Emoji::CHARACTER_TIMER_CLOCK, 'git_sha' => $gitHash]);
$buildDate = Carbon::parse($this->environment['BUILD_DATE']);
$this->logger->info('{emoji} Built on {build_date}, {build_ago}', ['emoji' => Emoji::CHARACTER_TIMER_CLOCK, 'build_date' => $buildDate->toDateTimeString(), 'build_ago' => $buildDate->ago()]);
try {
$this->stateHasChanged();
} catch (ConnectException $connectException) {
$this->logger->critical(sprintf('%s Could not connect to docker socket! Did you map it?', Emoji::CHARACTER_CRYING_CAT));
$this->logger->critical('{emoji} Could not connect to docker socket! Did you map it?', ['emoji' => Emoji::CHARACTER_CRYING_CAT]);
exit;
}
@ -625,6 +650,11 @@ class Bouncer
break;
case 'BOUNCER_HOST_OVERRIDE':
$bouncerTarget->setHostOverride($eVal);
break;
case 'BOUNCER_LETSENCRYPT':
$bouncerTarget->setLetsEncrypt(in_array(strtolower($eVal), ['yes', 'true'], true));