Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# socket-proxy

## Latest image
- `wollomatic/socket-proxy:1.11.4` / `ghcr.io/wollomatic/socket-proxy:1.11.4`
- `wollomatic/socket-proxy:1.12.0` / `ghcr.io/wollomatic/socket-proxy:1.12.0`
- `wollomatic/socket-proxy:1` / `ghcr.io/wollomatic/socket-proxy:1`

> [!IMPORTANT]
Expand Down Expand Up @@ -93,17 +93,22 @@ Use Go's regexp syntax to create the patterns for these parameters. To avoid ins
Examples (command-line):
+ `'-allowGET=/v1\..{1,2}/(version|containers/.*|events.*)'` could be used for allowing access to the docker socket for Traefik v2.
+ `'-allowHEAD=.*'` allows all HEAD requests.
+ `'-allowGET=/version -allowGET=/_ping'` use allow `GET` multiple times

Examples (env variables):
+ `'SP_ALLOW_GET="/v1\..{1,2}/(version|containers/.*|events.*)"'` could be used for allowing access to the docker socket for Traefik v2.
+ `'SP_ALLOW_HEAD=".*"'` allows all HEAD requests.
+ `'SP_ALLOW_GET="/version" SP_ALLOW_GET_2="/_ping"'` use allow `GET` multiple times

For more information, refer to the [Go regexp documentation](https://golang.org/pkg/regexp/syntax/).

An excellent online regexp tester is [regex101.com](https://regex101.com/).

To determine which HTTP requests your client application uses, you could switch socket-proxy to debug log level and look at the log output while allowing all requests in a secure environment.

> [!NOTE]
> Starting with version 1.12.0, the socket-proxy can set multiple -allow* in params, environment, or docker labels.

#### Setting up bind mount restrictions

By default, socket-proxy does not restrict bind mounts. If you want to add an additional layer of security by restricting which directories can be used as bind mount sources, you can use the `-allowbindmountfrom` parameter or the `SP_ALLOWBINDMOUNTFROM` environment variable.
Expand Down Expand Up @@ -135,6 +140,8 @@ services:
- docker-proxynet # this should be only restricted to traefik and socket-proxy
labels:
- 'socket-proxy.allow.get=.*' # allow all GET requests to socket-proxy
- 'socket-proxy.allow.head=/version' # HEAD `/version` requests to socket-proxy
- 'socket-proxy.allow.head.1=/exec' # another HEAD `exec` requests to socket-proxy
```

When this is used, it is not necessary to specify the container in `-allowfrom` as the presence of the allowlist labels will grant corresponding access.
Expand Down Expand Up @@ -227,15 +234,15 @@ To log the API calls of the client application, set the log level to `DEBUG` and
socket-proxy can be configured via command-line parameters or via environment variables. If both command-line parameters and environment variables are set, the environment variable will be ignored.

| Parameter | Environment Variable | Default Value | Description |
|--------------------------------|----------------------------------|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ------------------------------ | -------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-allowfrom` | `SP_ALLOWFROM` | `127.0.0.1/32` | Specifies the IP addresses or hostnames (comma-separated) of the clients or the hostname of one specific client allowed to connect to the proxy. The default value is `127.0.0.1/32`, which means only localhost is allowed. This default configuration may not be useful in most cases, but it is because of a secure-by-default design. To allow all IPv4 addresses, set `-allowfrom=0.0.0.0/0`. Alternatively, hostnames can be set, for example `-allowfrom=traefik`, or `-allowfrom=traefik,dozzle`. Please remember that socket-proxy should never be exposed to a public network, regardless of this extra security layer. |
| `-allowbindmountfrom` | `SP_ALLOWBINDMOUNTFROM` | (not set) | Specifies the directories (comma-separated) that are allowed as bind mount sources. If not set, no bind mount restrictions are applied. When set, only bind mounts from the specified directories or their subdirectories are allowed. Each directory must start with `/`. For example, `-allowbindmountfrom=/home,/var/log` allows bind mounts from `/home`, `/var/log`, and any subdirectories. |
| `-allowhealthcheck` | `SP_ALLOWHEALTHCHECK` | (not set/false) | If set, it allows the included health check binary to check the socket connection via TCP port 55555 (socket-proxy then listens on `127.0.0.1:55555/health`) |
| `-listenip` | `SP_LISTENIP` | `127.0.0.1` | Specifies the IP address the server will bind on. Default is only the internal network. |
| `-logjson` | `SP_LOGJSON` | (not set/false) | If set, it enables logging in JSON format. If unset, socket-proxy logs in plain text format. |
| `-loglevel` | `SP_LOGLEVEL` | `INFO` | Sets the log level. Accepted values are: `DEBUG`, `INFO`, `WARN`, `ERROR`. |
| `-proxyport` | `SP_PROXYPORT` | `2375` | Defines the TCP port the proxy listens to. |
| `-shutdowngracetime` | `SP_SHUTDOWNGRACETIME` | `10` | Defines the time in seconds to wait before forcing the shutdown after SIGTERM or SIGINT (socket-proxy first tries to gracefully shut down the TCP server) | |
| `-shutdowngracetime` | `SP_SHUTDOWNGRACETIME` | `10` | Defines the time in seconds to wait before forcing the shutdown after SIGTERM or SIGINT (socket-proxy first tries to gracefully shut down the TCP server) |
| `-socketpath` | `SP_SOCKETPATH` | `/var/run/docker.sock` | Specifies the UNIX socket path to connect to. By default, it connects to the Docker daemon socket. |
| `-stoponwatchdog` | `SP_STOPONWATCHDOG` | (not set/false) | If set, socket-proxy will be stopped if the watchdog detects that the unix socket is not available. |
| `-watchdoginterval` | `SP_WATCHDOGINTERVAL` | `0` | Check for socket availability every x seconds (disable checks, if not set or value is 0) |
Expand Down Expand Up @@ -269,6 +276,7 @@ socket-proxy can be configured via command-line parameters or via environment va

1.11 - add per-container allowlists specified by Docker container labels (thanks [@amanda-wee](https://github.com/amanda-wee))

1.12 - support use of allow* multiple times in env, flag and docker labels (thanks [@qianlongzt](https://github.com/qianlongzt))

## License

Expand Down
12 changes: 11 additions & 1 deletion cmd/socket-proxy/handlehttprequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log/slog"
"net"
"net/http"
"regexp"

"github.com/wollomatic/socket-proxy/internal/config"
)
Expand All @@ -24,7 +25,7 @@ func handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
communicateBlockedRequest(w, r, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !allowed.MatchString(r.URL.Path) { // path does not match regex -> not allowed
if !matchURL(allowed, r.URL.Path) { // path does not match regex -> not allowed
communicateBlockedRequest(w, r, "path not allowed", http.StatusForbidden)
return
}
Expand All @@ -40,6 +41,15 @@ func handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
socketProxy.ServeHTTP(w, r) // #nosec G704 - Request target is always the specified socket
}

func matchURL(allowedURIs []*regexp.Regexp, requestURI string) bool {
for _, allowedURI := range allowedURIs {
if allowedURI.MatchString(requestURI) {
return true
}
}
return false
}

// return the relevant allowlist
func determineAllowList(r *http.Request) (config.AllowList, bool) {
if cfg.ProxySocketEndpoint == "" { // do not perform this check if we proxy to a unix socket
Expand Down
Loading
Loading