Search by

filippo-toso / wireguard-transport

filippo.toso

PSR-18 HTTP client that sends requests through a userspace WireGuard tunnel.

Package info

github.com/filippotoso/wireguard-transport

pkg:composer/filippo-toso/wireguard-transport

Statistics

Installs: 3

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-10-31 19:58 UTC

This package is auto-updated.

Last update: 2026-10-31 19:59:19 UTC


README

A PSR-18 HTTP client that sends those requests through a WireGuard tunnel.

The handshake, encryption, and TCP stack live in this process. Other programs keep the host's normal routes. Nothing here needs root, a TUN device, or a separate WireGuard binary.

Third-party libraries can depend on this package and pass any PSR-7 request to sendRequest(). filippo-toso/wireguard-http and filippo-toso/wireguard-proxy are built on it.

Requirements

  • PHP 8.2 or newer, with the openssl and sodium extensions

Install

composer require filippo-toso/wireguard-transport

Usage

use FilippoToso\WireguardTransport\WireguardTransport;
use GuzzleHttp\Psr7\Request;

$client = WireguardTransport::withConfigFile(__DIR__ . '/wg0.conf');

$response = $client->sendRequest(new Request('GET', 'https://ifconfig.co/json'));

$address = json_decode((string) $response->getBody(), true)['ip'];

$client->disconnect();

withConfig() accepts the configuration text instead of a file.

sendRequest() returns the next HTTP response and does not follow redirects. Call withFollowRedirects(true) when this client should follow them. withTimeout(), withConnectTimeout(), and withVerify(false) adjust that one call and share the same tunnel.

Hostnames in request URLs are resolved inside the tunnel, using the DNS addresses from the configuration. The WireGuard endpoint hostname is resolved on the host, because that UDP socket is how the tunnel itself is reached.

A failed network call throws FilippoToso\WireguardTransport\Exception\NetworkException, which is a PSR-18 network exception. A request this client cannot send, such as a URL that is not absolute http(s), throws InvalidRequestException. A disconnected tunnel throws TunnelException. All three implement Psr\Http\Client\ClientExceptionInterface.

Configuration files

Pass a normal wg-quick file: one [Interface] and at least one [Peer], including PrivateKey, Address, PublicKey, AllowedIPs, and Endpoint. Repeated Address, DNS, and AllowedIPs lines are joined. A bare IP is treated as /32 or /128. DNS, MTU, ListenPort, PresharedKey, and PersistentKeepalive are kept. DNS search domains are ignored. Table, FwMark, SaveConfig, and the PreUp / PostUp / PreDown / PostDown hooks are accepted and ignored, because this process does not run shell hooks. CheckAlive and CheckAliveInterval are accepted and ignored.

A key may be an environment-variable reference such as $WG_PRIVATE_KEY or ${WG_PUBLIC_KEY}. The variable is read when the tunnel starts.

disconnect() drops the session. Further requests on that client fail. The tunnel also stops when the last client using it is destroyed.

Limitations

  • Traffic inside the tunnel is IPv4. IPv6 destinations and IPv6 WireGuard endpoints are rejected.
  • TLS is 1.2, terminated by OpenSSL.
  • HTTP is 1.1.
  • AmneziaWG and other non-standard keys are rejected.