mirror of
https://github.com/yusing/godoxy.git
synced 2026-01-11 22:30:47 +01:00
docs: add per package README for implementation details (AI generated with human review)
This commit is contained in:
54
socket-proxy/cmd/README.md
Normal file
54
socket-proxy/cmd/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# socket-proxy/cmd
|
||||
|
||||
The entry point for the Docker Socket Proxy sub-project, a secure proxy that exposes the Docker socket with fine-grained access control.
|
||||
|
||||
## Overview
|
||||
|
||||
This package provides a minimal main entry point that starts the Docker socket proxy server. The proxy acts as a gatekeeper, allowing or denying access to Docker API endpoints based on configured permissions.
|
||||
|
||||
This is similar to [lscr.io/linuxserver/socket-proxy](https://github.com/linuxserver/docker-socket-proxy) but:
|
||||
|
||||
- **No EOF errors**: Properly handles keep-alive connections to avoid occasional EOF errors that plague other implementations
|
||||
- **GoDoxy integration**: Designed to work seamlessly with GoDoxy for container auto-discovery and route management
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[HTTP Client] --> B[Socket Proxy]
|
||||
B --> C{Deny?}
|
||||
C -->|Yes| D[403 Forbidden]
|
||||
C -->|No| E[Docker Socket]
|
||||
E --> F[Docker Daemon]
|
||||
```
|
||||
|
||||
## Main Function
|
||||
|
||||
```go
|
||||
func main() {
|
||||
// Validates that ListenAddr is set
|
||||
// Starts HTTP server on configured address
|
||||
// Uses socketproxy.NewHandler() for request routing
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The socket proxy is configured via environment variables:
|
||||
|
||||
| Variable | Description | Default |
|
||||
| -------------------- | -------------------------------- | ---------------------- |
|
||||
| `DOCKER_SOCKET` | Path to Docker socket | `/var/run/docker.sock` |
|
||||
| `LISTEN_ADDR` | Address to listen on | (empty - disabled) |
|
||||
| `DOCKER_SOCKET_ADDR` | Alternative name for LISTEN_ADDR | (empty) |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Start the socket proxy
|
||||
DOCKER_SOCKET=/var/run/docker.sock LISTEN_ADDR=:2375 go run main.go
|
||||
```
|
||||
|
||||
## Related Packages
|
||||
|
||||
- `socketproxy/pkg` - Core proxy implementation with route handling and reverse proxy logic
|
||||
100
socket-proxy/pkg/README.md
Normal file
100
socket-proxy/pkg/README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# socket-proxy/pkg
|
||||
|
||||
Core package for the Docker Socket Proxy, providing secure access to the Docker API with endpoint filtering and access control.
|
||||
|
||||
## Overview
|
||||
|
||||
This package implements a secure proxy that controls access to Docker socket API endpoints. It supports fine-grained permissions for different Docker operations and can restrict HTTP methods (GET-only or GET+POST).
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[HTTP Request] --> B[NewHandler Router]
|
||||
B --> C{Method Allowed?}
|
||||
C -->|No| D[405 Method Not Allowed]
|
||||
C -->|Yes| E{Path Allowed?}
|
||||
E -->|No| F[403 Forbidden]
|
||||
E -->|Yes| G[Docker Socket Handler]
|
||||
G --> H[Reverse Proxy]
|
||||
H --> I[Docker Daemon]
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### Environment Configuration (`env.go`)
|
||||
|
||||
Global configuration flags loaded from environment variables:
|
||||
|
||||
| Variable | Type | Default | Description |
|
||||
| ------------------ | ------ | ---------------------- | --------------------------- |
|
||||
| `DockerSocket` | string | `/var/run/docker.sock` | Path to Docker socket |
|
||||
| `ListenAddr` | string | (empty) | HTTP listen address |
|
||||
| `DockerPost` | bool | `false` | Allow POST methods |
|
||||
| `DockerRestarts` | bool | `false` | Allow container restarts |
|
||||
| `DockerStart` | bool | `false` | Allow container starts |
|
||||
| `DockerStop` | bool | `false` | Allow container stops |
|
||||
| `DockerAuth` | bool | `false` | Allow /auth endpoints |
|
||||
| `DockerBuild` | bool | `false` | Allow /build endpoints |
|
||||
| `DockerCommit` | bool | `false` | Allow /commit endpoints |
|
||||
| `DockerContainers` | bool | `false` | Allow /containers endpoints |
|
||||
| `DockerEvents` | bool | `true` | Allow /events endpoints |
|
||||
| `DockerExec` | bool | `false` | Allow /exec endpoints |
|
||||
| `DockerImages` | bool | `false` | Allow /images endpoints |
|
||||
| `DockerInfo` | bool | `false` | Allow /info endpoints |
|
||||
| `DockerNetworks` | bool | `false` | Allow /networks endpoints |
|
||||
| `DockerPing` | bool | `true` | Allow /\_ping endpoints |
|
||||
| `DockerServices` | bool | `false` | Allow /services endpoints |
|
||||
| `DockerSystem` | bool | `false` | Allow /system endpoints |
|
||||
| `DockerVersion` | bool | `true` | Allow /version endpoints |
|
||||
| `DockerVolumes` | bool | `false` | Allow /volumes endpoints |
|
||||
|
||||
### Request Handler (`handler.go`)
|
||||
|
||||
The `NewHandler()` function creates an HTTP router with:
|
||||
|
||||
- Path-based access control (allowed/denied paths)
|
||||
- HTTP method filtering (GET-only or GET+POST)
|
||||
- Version prefix support (e.g., `/v1.41/containers`)
|
||||
- Unix domain socket proxying
|
||||
|
||||
### Reverse Proxy (`reverseproxy/reverse_proxy.go`)
|
||||
|
||||
Based on Go's standard library reverse proxy with enhancements:
|
||||
|
||||
- Hop-by-hop header removal
|
||||
- WebSocket/h2c upgrade handling
|
||||
- Trailer support
|
||||
- Context-aware request cancellation
|
||||
|
||||
## Usage Example
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
socketproxy "github.com/yusing/godoxy/socketproxy/pkg"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configuration is loaded from environment variables
|
||||
if socketproxy.ListenAddr == "" {
|
||||
log.Fatal("Docker socket address is not set")
|
||||
}
|
||||
log.Printf("Docker socket listening on: %s", socketproxy.ListenAddr)
|
||||
http.ListenAndServe(socketproxy.ListenAddr, socketproxy.NewHandler())
|
||||
}
|
||||
```
|
||||
|
||||
## Security Features
|
||||
|
||||
1. **Endpoint Whitelisting**: Only explicitly allowed endpoints are accessible
|
||||
1. **Method Restrictions**: Can restrict to GET-only or allow POST
|
||||
1. **Connection Keep-Alive**: Maintains persistent connections to Docker socket
|
||||
1. **Header Filtering**: Removes hop-by-hop headers to prevent spoofing
|
||||
|
||||
## Docker Integration
|
||||
|
||||
The proxy connects to the Docker daemon via Unix socket and proxies all allowed requests. The Docker API version prefix is handled automatically for backward compatibility.
|
||||
73
socket-proxy/pkg/reverseproxy/README.md
Normal file
73
socket-proxy/pkg/reverseproxy/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Socket Proxy Reverse Proxy
|
||||
|
||||
This package provides an HTTP reverse proxy implementation for proxying requests to Unix sockets (typically Docker sockets). It is based on Go's `net/http/httputil.ReverseProxy` with simplifications for socket proxying use cases.
|
||||
|
||||
## Differences from `net/http/httputil.ReverseProxy`
|
||||
|
||||
| Feature | stdlib `httputil.ReverseProxy` | This package |
|
||||
| --------------------- | ------------------------------ | ----------------------------------- |
|
||||
| Request modification | `Director` or `Rewrite` | `Director` only |
|
||||
| Response modification | `ModifyResponse` hook | Not supported |
|
||||
| Buffering | Uses `io.Copy` | Uses `ioutils.CopyCloseWithContext` |
|
||||
| Flush support | `Flush()` method | Not exposed |
|
||||
|
||||
### Key Simplifications
|
||||
|
||||
1. **Director only**: Only the `Director` function is supported. The stdlib's `Rewrite` type and `ModifyResponse` hook are removed.
|
||||
|
||||
2. **Context-aware body copying**: Uses `ioutils.CopyCloseWithContext` which:
|
||||
|
||||
- Respects request context for cancellation
|
||||
- Uses `Content-Length` for optimal copying when available
|
||||
- Properly handles trailer headers
|
||||
|
||||
3. **No buffering**: Unlike the stdlib which can buffer responses, this implementation streams directly to the client.
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
rp := &reverseproxy.ReverseProxy{
|
||||
Director: func(req *http.Request) {
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = "api.moby.localhost"
|
||||
req.RequestURI = req.URL.String()
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return net.DialTimeout("unix", "/var/run/docker.sock", 5*time.Second)
|
||||
},
|
||||
DisableCompression: true,
|
||||
},
|
||||
}
|
||||
|
||||
http.HandleFunc("/", rp.ServeHTTP)
|
||||
http.ListenAndServe(":2375", nil)
|
||||
```
|
||||
|
||||
## Socket Proxy Integration
|
||||
|
||||
The socket proxy uses this package in `socket-proxy/pkg/handler.go`:
|
||||
|
||||
```go
|
||||
func dockerSocketHandler(socket string) http.HandlerFunc {
|
||||
rp := &reverseproxy.ReverseProxy{
|
||||
Director: func(req *http.Request) {
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = "api.moby.localhost"
|
||||
req.RequestURI = req.URL.String()
|
||||
},
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
dialer := &net.Dialer{KeepAlive: 1 * time.Second}
|
||||
return dialer.DialContext(ctx, "unix", socket)
|
||||
},
|
||||
DisableCompression: true,
|
||||
},
|
||||
}
|
||||
return rp.ServeHTTP
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This code is based on Go's `net/http/httputil` and is licensed under the BSD-style license found at the top of `reverse_proxy.go`.
|
||||
Reference in New Issue
Block a user