Releases: ironsh/iron-proxy
v0.43.0
New: Disable Built-In DNS Server
iron-proxy's DNS server can now be disabled entirely via dns.enabled: false (or the IRON_DNS_ENABLED environment variable). When disabled, the proxy skips the :53 listener, drops the dns.proxy_ip requirement, and does not start the DNS server at all. Existing deployments are unaffected: the field defaults to true.
This is useful when clients reach the proxy via explicit HTTP_PROXY or HTTPS_PROXY environment variables rather than DNS interception, removing the need to run a DNS listener in those environments.
dns:
enabled: falseNew: Per-Upstream Postgres Session Settings
Postgres upstreams now support a settings list of session variables (GUCs) the proxy injects at session start, before the SET ROLE downgrade. Settings are applied via set_config with bound parameters (no value quoting), so they are safe to use with untrusted values.
The proxy pins every name in the list: clients may not SET, RESET, or set_config a pinned name afterwards. RESET ALL and DISCARD ALL are now also blocked whenever the proxy manages a role or session settings, closing a gap where those commands could previously undo the managed role. This makes settings suitable as a security boundary, for example passing a tenant identifier that a Row-Level Security policy keys off.
upstreams:
- database: appdb
dsn:
type: env
var: PG_APPDB_DSN
role: tenant_role
settings:
- name: app.tenant_id
value: centaurNames must be bare or dotted GUC identifiers; role and session_authorization are reserved (use the role field for those). Values are static per-upstream. Postgres support is experimental.
Changelog
v0.42.0
New: Postgres Single-Listener Architecture
The postgres configuration has been redesigned from a list of independent listeners to a single shared listener fronting multiple upstream databases. One bind address serves many upstreams: the client selects the upstream by the dbname it sends in its startup message, and the proxy routes accordingly. A single shared credential handles all client authentication; routing is by database name, so per-database credentials are not required.
Multi-statement Simple Queries are now also supported. The proxy forwards a batch as long as every statement passes the role policy, and rejects the batch only if any statement attempts a role mutation (SET ROLE, set_config('role', ...)) or a DO block.
# Before
postgres:
- name: primary
listen: ":5432"
upstream:
host: "db.internal"
port: 5432
sslmode: "require"
user_env: "PG_UPSTREAM_USER"
password_env: "PG_UPSTREAM_PASSWORD"
database: "appdb"
client:
user: "app_user"
password_env: "PG_PROXY_PASSWORD"
role: "tenant_role"
# After
postgres:
listen: ":5432"
client:
user: app_user
password_env: PG_PROXY_PASSWORD
upstreams:
- database: appdb
dsn:
type: env
var: PG_APPDB_DSN
role: tenant_role
- database: analyticsdb
dsn:
type: env
var: PG_ANALYTICS_DSN
role: analytics_roleThis is a breaking config change for existing Postgres users. Migrate each entry in your postgres: list to an upstream under the new upstreams: key, replacing the per-listener upstream.host/port/... fields with a DSN source block. Postgres support is experimental.
New: File Secret Source
A new file secret source reads the secret from a path on disk. The file is re-read on every POST /v1/reload and on ttl expiry, so a long-lived proxy can pick up a rotated credential without restarting. Write the secret atomically (write-temp + rename) and call reload.
- source:
type: file
path: /etc/iron-proxy/secrets/OPENAI_API_KEY
proxy_value: "proxy-token-123"
match_headers: ["Authorization"]
rules:
- host: "api.openai.com"Optional ttl and failure_ttl are supported. The value is the exact file contents (no trimming), so the writer controls trailing whitespace. Thanks to @drewstone for the contribution.
New: Outbound Proxy Routing
iron-proxy now routes its own outbound connections through an upstream SOCKS5 or HTTP CONNECT proxy. The standard HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables are honored automatically, so most deployments need no config change. An optional upstream_proxy block is available when environment variables aren't convenient.
proxy:
upstream_proxy:
http_proxy: "http://proxy.corp:3128"
https_proxy: "http://proxy.corp:3128"
no_proxy: "localhost,127.0.0.1,.internal.example.com"This covers the HTTP/HTTPS forward data path (including CONNECT in mitm mode) and the OAuth credential-refresh client. Raw TCP tunnels (SNI-only passthrough, WebSocket) still dial directly. Note: when an upstream proxy is in use, upstream_deny_cidrs is enforced against the proxy's address rather than the final target, since the proxy resolves and connects to the target on iron-proxy's behalf.
New: 1Password Config Simplification
The host_env and token_env config fields on the 1password and 1password_connect secret sources have been removed. The SDK environment variable conventions (OP_SERVICE_ACCOUNT_TOKEN for 1password; OP_CONNECT_HOST and OP_CONNECT_TOKEN for 1password_connect) are now the only supported approach.
This is a breaking config change for 1password and 1password_connect users who set host_env or token_env. Remove those fields from your config.
Fixes
- Fixed
aws_authrejecting HTTPS CONNECT tunnel setup with 400/missing_sigv4before the signed request was ever sent. The synthetic CONNECT request used for tunnel policy checks can never carry a SigV4 signature; the transform now passes it through and signs the post-MITM request as intended. This affected boto3 and other clients routing HTTPS through a CONNECT proxy. Thanks to @0xdiid for the contribution. - Fixed percent-encoded reserved characters (e.g.,
%2F) being decoded before the upstream request was constructed, breaking APIs like GCS that route on encoded slashes within a path segment. - Fixed
gcp_auth,hmac_sign, andoauth_tokentransforms being silently dropped in managed mode at startup and on every reload.
Changelog
- 57a2cc3 feat(broker): add iron-token-broker for race-free OAuth refresh coordination (#141)
- 53ec28d build: release iron-token-broker alongside iron-proxy (#142)
- 5a06a6d feat(secrets): add token_broker source backed by iron-token-broker (#143)
- 51c3220 refactor(secrets): drop env-name overrides for 1password and 1password_connect (#144)
- b2d5b9a ci: release iron-token-broker on prefixed iron-token-broker/v* tags (#145)
- 65276fd ci: split release workflow per binary and allow gumroad egress (#146)
- 4d96a9f fix(ci): always log in to Docker Hub on release tags (#147)
- 0c2fc94 fix(release): auto-detect prereleases and scope broker changelog (#148)
- 510668d fix(release): ignore broker tags when computing iron-proxy previous release (#149)
- 882726c feat(broker): accept 1Password titles in store secret_ref (#150)
- be21d37 feat(broker): support token_endpoint_headers on credentials (#151)
- 96fedf0 docs: add AGENTS.md with Go conventions and review guidance (#152)
- b396dcc refactor: centralize case-sensitive header handling in internal/headers (#153)
- ab9e8e0 refactor(integration_test): consolidate shared helpers (#154)
- 8f1d8ef fix(proxy): preserve percent-encoded reserved chars in upstream path (#156)
- 7159126 fix(awsauth): let CONNECT through the tunnel policy check (#167)
- 6326e3f feat(postgres): allow multi-statement queries that pass the role policy (#168)
- 0de6a1b refactor(controlplane): authenticate with a fixed bearer token (#169)
- 7e66d72 feat(scripts): add dev-managed boot script and prefix sync path with /api (#170)
- cfa25af feat(postgres): derive listeners from control-plane sync section (#171)
- 81a3976 feat(controlplane): apply synced transforms in managed pipeline (#172)
- f57e475 refactor(secrets): remove token_broker transform (#177)
- feb3242 feat(postgres): single listener fronting database-routed upstreams (#179)
- 28f0f80 build(deps): bump github.com/jackc/pgx/v5 from 5.9.2 to 5.10.0 (#175)
- 93ce7dc build(deps): bump the aws-sdk-go group with 5 updates (#174)
- 064f6cb build(deps): bump actions/checkout from 6.0.2 to 6.0.3 (#173)
- cdda920 build(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp (#163)
- 1163be8 build(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc (#165)
- 62bc31b build(deps): bump the aws-sdk-go group with 2 updates (#161)
- 451822e build(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.2.1 (#159)
- 9e3d739 build(deps): bump docker/setup-buildx-action from 4.0.0 to 4.1.0 (#160)
- 3a1a2c2 build(deps): bump docker/login-action from 4.1.0 to 4.2.0 (#158)
- a985a39 build(deps): bump docker/setup-qemu-action from 4.0.0 to 4.1.0 (#157)
- 7e6a694 feat(secrets): add file source re-read on reload (#181)
- afdeca2 feat(proxy): route outbound through upstream SOCKS5/HTTP CONNECT proxy (#182)
- 26333fb chore: remove token broker references from proxy (#183)
v0.42.0-rc.8
v0.42.0-rc.7
v0.42.0-rc.6
Changelog
- 3a1a2c2 build(deps): bump docker/login-action from 4.1.0 to 4.2.0 (#158)
- 9e3d739 build(deps): bump docker/setup-buildx-action from 4.0.0 to 4.1.0 (#160)
- a985a39 build(deps): bump docker/setup-qemu-action from 4.0.0 to 4.1.0 (#157)
- 1163be8 build(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc (#165)
- 451822e build(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.2.1 (#159)
- 62bc31b build(deps): bump the aws-sdk-go group with 2 updates (#161)
- cfa25af feat(postgres): derive listeners from control-plane sync section (#171)
v0.42.0-rc.5
v0.42.0-rc.4
v0.42.0-rc.3
v0.42.0-rc.2
Changelog
- 96fedf0 docs: add AGENTS.md with Go conventions and review guidance (#152)
- 882726c feat(broker): accept 1Password titles in store secret_ref (#150)
- be21d37 feat(broker): support token_endpoint_headers on credentials (#151)
- 510668d fix(release): ignore broker tags when computing iron-proxy previous release (#149)
- b396dcc refactor: centralize case-sensitive header handling in internal/headers (#153)