PHPackages                             php-opcua/opcua-client-ext-reverse-connect - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. php-opcua/opcua-client-ext-reverse-connect

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

php-opcua/opcua-client-ext-reverse-connect
==========================================

OPC UA Reverse Connect (ReverseHello) listener for PHP — extends opcua-client, OPC UA Part 6 §7.1.2.3

v4.4.0(1mo ago)00MITPHPPHP ^8.2

Since Jun 4Pushed 1mo agoCompare

[ Source](https://github.com/php-opcua/opcua-client-ext-reverse-connect)[ Packagist](https://packagist.org/packages/php-opcua/opcua-client-ext-reverse-connect)[ Docs](https://github.com/php-opcua/opcua-client-ext-reverse-connect)[ RSS](/packages/php-opcua-opcua-client-ext-reverse-connect/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (1)Dependencies (5)Versions (2)Used By (0)

**OPC UA Reverse Connect — PHP listener**
=========================================

[](#opc-ua-reverse-connect--php-listener)

    ![OPC UA Reverse Connect — PHP listener](assets/logo-light.svg)

 [![Tests](https://camo.githubusercontent.com/c15aababa341e1e0f37628fd4a8ed93cbae710f9a8682f7c56cd7c0edb4ded2e/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7068702d6f706375612f6f706375612d636c69656e742d6578742d726576657273652d636f6e6e6563742f74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/php-opcua/opcua-client-ext-reverse-connect/actions/workflows/tests.yml) [![Coverage](https://camo.githubusercontent.com/e1b5aca0663fbce8df419d984cdcdbe8198811f64d4180a8ed369cb8a8c5a485/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f7068702d6f706375612f6f706375612d636c69656e742d6578742d726576657273652d636f6e6e6563743f7374796c653d666c61742d737175617265266c6f676f3d636f6465636f76)](https://codecov.io/gh/php-opcua/opcua-client-ext-reverse-connect) [![Latest Version](https://camo.githubusercontent.com/3dcfc5ee267ebc6cc4d5868efa874f0626ec8a268c10fc7eb1f2eb3a4a2a2e38/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068702d6f706375612f6f706375612d636c69656e742d6578742d726576657273652d636f6e6e6563743f7374796c653d666c61742d737175617265266c6162656c3d7061636b6167697374)](https://packagist.org/packages/php-opcua/opcua-client-ext-reverse-connect) [![PHP Version](https://camo.githubusercontent.com/fd58a64eef1e003c95a712e9706650f04ab245f8e4d1b1c9fe4a74547b5c32a3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7068702d6f706375612f6f706375612d636c69656e742d6578742d726576657273652d636f6e6e6563743f7374796c653d666c61742d737175617265)](https://packagist.org/packages/php-opcua/opcua-client-ext-reverse-connect) [![License](https://camo.githubusercontent.com/d9a46bf9e5a0aa09085841bd4c03f6ca8f7c75ac62c167c01fdacbc12efa1940/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7068702d6f706375612f6f706375612d636c69656e742d6578742d726576657273652d636f6e6e6563743f7374796c653d666c61742d737175617265)](LICENSE)

 [![Linux](https://camo.githubusercontent.com/88a96af546255df6414fb878e65861f03abd9cd7c69fe0c652b32d10e1dc2b84/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f4c696e75782de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6c696e7578266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/88a96af546255df6414fb878e65861f03abd9cd7c69fe0c652b32d10e1dc2b84/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f4c696e75782de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6c696e7578266c6f676f436f6c6f723d7768697465) [![macOS](https://camo.githubusercontent.com/9abd62edee5c8e38df116839daa54deb7e5b2054d4bcb856529f5cd92ada8b74/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f6d61634f532de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6170706c65266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/9abd62edee5c8e38df116839daa54deb7e5b2054d4bcb856529f5cd92ada8b74/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f6d61634f532de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d6170706c65266c6f676f436f6c6f723d7768697465) [![Windows](https://camo.githubusercontent.com/67b9f3090b3bbef27712496e616a0a0f0ead78d1a3a092a80b74df716dda8a6b/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f57696e646f77732de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d77696e646f77733131266c6f676f436f6c6f723d7768697465)](https://camo.githubusercontent.com/67b9f3090b3bbef27712496e616a0a0f0ead78d1a3a092a80b74df716dda8a6b/68747470733a2f2f637573746f6d2d69636f6e2d6261646765732e64656d6f6c61622e636f6d2f62616467652f57696e646f77732de29c932d3265613434663f7374796c653d666c61742d737175617265266c6f676f3d77696e646f77733131266c6f676f436f6c6f723d7768697465)

---

Client-side listener for **OPC UA Reverse Connect** ([Part 6 §7.1.2.3](https://reference.opcfoundation.org/Core/Part6/v105/docs/7.1.2.3)). Extension of [`php-opcua/opcua-client`](https://github.com/php-opcua/opcua-client). The server dials out, the client accepts; everything after the opening `ReverseHello` frame is the standard UA-TCP protocol.

Reverse Connect inverts who initiates the underlying TCP connection. It is the pattern of choice when the server is behind NAT or a one-way firewall: the device dials outward, your PHP application listens for the incoming socket, validates the announced `ServerUri`, then proceeds with the normal UA-TCP handshake — secure channel, session, service calls — exactly as if you had connected the regular way.

**What you can do with it:**

- **Bind a listener** on any host/port and accept inbound `RHE` frames from one or many announcing servers
- **Validate** each frame against an explicit whitelist of trusted `ServerUri` values before letting the UA-TCP pipeline touch the socket
- **Hand the live socket** to the standard `ClientBuilder` via the v4.4.0 `TcpTransport::fromConnectedSocket()` seam, then use the resulting `Client` like any other
- **Observe** the flow with three PSR-14 events — `ReverseHelloReceived`, `ReverseConnectAccepted`, `ReverseConnectRejected` — and a PSR-3 logger
- **Cover failure modes explicitly** with four typed exceptions (parse, validation, timeout, plumbing) rooted in a single base class

Pure PHP, no native extensions, no event loop dependency.

> **Note:** This package only ships the listener-side machinery. The OPC UA server you talk to must support Reverse Connect on its end and be told (via configuration, MQTT, an HTTPS callback — whatever fits your topology) to dial back to the listener's host and port. For integration testing the [`uanetstandard-test-suite`](https://github.com/php-opcua/uanetstandard-test-suite) v1.4.0+ exposes two Method nodes — `StartReverseConnect` and `StopReverseConnect` — that let a regular client trigger the outbound dial.

### How it relates to `opcua-client`

[](#how-it-relates-to-opcua-client)

The only seam in the core package is the `TcpTransport::fromConnectedSocket()` factory (added in v4.4.0) and the matching `ManagesConnectionTrait::performConnect()` skip when the transport is already connected. Everything else — the listener, the parser, the whitelist validator, the bridge to `ClientBuilder` — lives here. Applications that do not need Reverse Connect take no extra dependency.

---

Quick Start
-----------

[](#quick-start)

```
composer require php-opcua/opcua-client-ext-reverse-connect
```

```
use PhpOpcua\Client\ClientBuilder;
use PhpOpcua\Client\ExtReverseConnect\ReverseConnectClientFactory;
use PhpOpcua\Client\ExtReverseConnect\ReverseConnectListener;
use PhpOpcua\Client\ExtReverseConnect\ReverseHelloValidator;
use PhpOpcua\Client\Security\SecurityMode;
use PhpOpcua\Client\Security\SecurityPolicy;

$listener = new ReverseConnectListener(
    bindHost: '0.0.0.0',
    bindPort: 4841,
    validator: new ReverseHelloValidator(['urn:my-edge-gateway:server']),
);
$listener->listen();

$session = $listener->accept(timeoutSeconds: 30.0);

$client = (new ReverseConnectClientFactory())->buildClient(
    $session,
    static fn (ClientBuilder $b) => $b
        ->setSecurityPolicy(SecurityPolicy::None)
        ->setSecurityMode(SecurityMode::None),
);

$value = $client->read('ns=2;s=Demo.Counter');
echo $value->getValue() . PHP_EOL;

$client->disconnect();
$listener->close();
```

That's it. Bind, accept, build, use, disconnect — five calls and you are reading values through a socket the server opened.

See It in Action
----------------

[](#see-it-in-action)

### Validate against a whitelist

[](#validate-against-a-whitelist)

```
use PhpOpcua\Client\ExtReverseConnect\ReverseHelloValidator;

$validator = new ReverseHelloValidator([
    'urn:gateway:plc-42',
    'urn:gateway:plc-43',
]);

// The listener uses ensureAccepted() internally; you can call it
// yourself on captured frames in tests or audit pipelines.
$validator->ensureAccepted($message);   // throws ReverseConnectRejectedException
$validator->isAccepted($message);       // bool — non-throwing variant
```

An empty whitelist refuses every incoming frame — the validator is **fail-secure by default**.

### React to events (PSR-14)

[](#react-to-events-psr-14)

```
use PhpOpcua\Client\ExtReverseConnect\Event\ReverseConnectAccepted;
use PhpOpcua\Client\ExtReverseConnect\Event\ReverseConnectRejected;
use PhpOpcua\Client\ExtReverseConnect\Event\ReverseHelloReceived;

$listener = new ReverseConnectListener(
    bindHost: '0.0.0.0',
    bindPort: 4841,
    validator: $validator,
    dispatcher: $yourPsr14Dispatcher,
);

// Listeners observe parseable RHEs, accepted sessions, and rejections.
class AuditHandler {
    public function onReceived(ReverseHelloReceived $event): void { /* ... */ }
    public function onAccepted(ReverseConnectAccepted $event): void { /* ... */ }
    public function onRejected(ReverseConnectRejected $event): void {
        Log::warning("Rejected {$event->message->serverUri}: {$event->reason}");
    }
}
```

Zero overhead when no dispatcher is provided — events are not constructed at all.

### Trigger the server from PHP (test suite flow)

[](#trigger-the-server-from-php-test-suite-flow)

```
use PhpOpcua\Client\Types\BuiltinType;
use PhpOpcua\Client\Types\NodeId;
use PhpOpcua\Client\Types\Variant;

$trigger = (new ClientBuilder())
    ->setSecurityPolicy(SecurityPolicy::None)
    ->setSecurityMode(SecurityMode::None)
    ->connect('opc.tcp://localhost:4840/UA/TestServer');

$trigger->call(
    NodeId::string(2, 'TestServer/ReverseConnect'),
    NodeId::string(2, 'TestServer/ReverseConnect/StartReverseConnect'),
    [
        new Variant(BuiltinType::String, 'host.docker.internal'),
        new Variant(BuiltinType::UInt16, $listenerPort),
    ],
);
```

In production the trigger is whatever you already have — HTTPS callback, MQTT push, a CLI on the gateway. The listener does not care how the server learned where to dial.

### Connect with full security

[](#connect-with-full-security)

```
$client = (new ReverseConnectClientFactory())->buildClient(
    $session,
    static fn (ClientBuilder $b) => $b
        ->setSecurityPolicy(SecurityPolicy::Basic256Sha256)
        ->setSecurityMode(SecurityMode::SignAndEncrypt)
        ->setClientCertificate('/certs/client.pem', '/certs/client.key', '/certs/ca.pem')
        ->setUserCredentials('operator', 'secret'),
);
```

Reverse Connect inverts the TCP direction; it does **not** change the OPC UA security model. Configure the builder inside the `$configure` closure the same way you would for a classic outbound client. Do not call `setTransport()` inside the closure — the factory has already wired one from the inherited socket.

### Run the loop

[](#run-the-loop)

```
while ($keepRunning) {
    try {
        $session = $listener->accept(timeoutSeconds: 5.0);
    } catch (ReverseConnectTimeoutException) {
        continue;
    } catch (ReverseConnectRejectedException $e) {
        Log::warning("Rejected reverse-connect from {$e->rejectedMessage->serverUri}: {$e->getMessage()}");
        continue;
    } catch (ReverseHelloParseException $e) {
        Log::warning("Malformed RHE: {$e->getMessage()}");
        continue;
    }

    handleSession($session);
}
$listener->close();
```

Why This Package?
-----------------

[](#why-this-package)

- **Tiny, focused surface** — six classes, four exceptions, three events. Everything else is `php-opcua/opcua-client`.
- **No event loop dependency** — bounded `accept(timeoutSeconds)` over `stream_select()`. Plug into your own loop or run a CLI worker.
- **Fail-secure validator** — empty whitelist refuses every frame; case-sensitive `ServerUri` match; `opc.tcp://` scheme enforced on the announced endpoint.
- **PSR everywhere** — PSR-3 logger and PSR-14 dispatcher both optional. No global state. No service locator.
- **Cross-platform** — pure PHP streams API; no Unix domain sockets, no FFI, no native extensions. Tested on Linux, macOS, and Windows.
- **Reuses the full core** — same `Client`, same security stack, same modules, same DTOs as `opcua-client`. The transport seam is `TcpTransport::fromConnectedSocket()`; the rest of the pipeline is untouched.
- **Thoroughly tested** — 44 unit tests + 4 end-to-end integration tests against UA-.NETStandard via [`uanetstandard-test-suite`](https://github.com/php-opcua/uanetstandard-test-suite) v1.4.0+.

Documentation
-------------

[](#documentation)

The published version of the documentation lives at . The Markdown sources ship under [`docs/`](docs/index.md):

SectionCovers**Getting started** — [Overview](docs/overview.md) · [Installation](docs/getting-started/installation.md) · [Quick start](docs/getting-started/quick-start.md)What it is, how to install, first listener**Concepts** — [How Reverse Connect works](docs/concepts/how-it-works.md)Wire format, lifecycle, security model**API** — [Listener](docs/api/listener.md) · [Validator](docs/api/validator.md) · [Factory](docs/api/factory.md) · [Events](docs/api/events.md)Constructor arguments, methods, rejection rules**Recipes** — [Docker host networking](docs/recipes/docker-host-networking.md)`extra_hosts` + `0.0.0.0` bind pattern**Reference** — [Exceptions](docs/reference/exceptions.md)Every exception, cause, and catch strategyTesting
-------

[](#testing)

```
./vendor/bin/pest                                          # everything
./vendor/bin/pest tests/Unit/                              # unit only (44 tests, no external deps)
./vendor/bin/pest tests/Integration/ --group=integration   # E2E (requires uanetstandard-test-suite v1.4.0+)
```

The integration suite expects the `opcua-no-security` service from `uanetstandard-test-suite` running on `opc.tcp://localhost:4840` with `extra_hosts: ["host.docker.internal:host-gateway"]` configured (already the case in v1.4.0+).

Ecosystem
---------

[](#ecosystem)

PackageDescription[opcua-client](https://github.com/php-opcua/opcua-client)Pure PHP OPC UA client (the core this extension hooks into)[opcua-client-ext-pubsub](https://github.com/php-opcua/opcua-client-ext-pubsub)OPC UA PubSub Subscriber — UDP + UADP + JSON[opcua-cli](https://github.com/php-opcua/opcua-cli)CLI tool — browse, read, write, watch, discover endpoints, manage certificates[opcua-client-nodeset](https://github.com/php-opcua/opcua-client-nodeset)Pre-generated PHP types from 51 OPC Foundation companion specifications[laravel-opcua](https://github.com/php-opcua/laravel-opcua)Laravel integration — service provider, facade, config[uanetstandard-test-suite](https://github.com/php-opcua/uanetstandard-test-suite)Docker-based OPC UA test servers (UA-.NETStandard) for integration testingCommunity
---------

[](#community)

Have questions, ideas, or want to share what you've built? Join the [GitHub Discussions](https://github.com/php-opcua/opcua-client/discussions).

Contributing
------------

[](#contributing)

Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) in the core repository for the shared code style and workflow.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md).

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance90

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

50d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/fb72ba5d2c05eec08d9556c0007f17a7d657d5187de1025a4a0525ace4ac8000?d=identicon)[GianfriAur](/maintainers/GianfriAur)

---

Top Contributors

[![GianfriAur](https://avatars.githubusercontent.com/u/16904504?v=4)](https://github.com/GianfriAur "GianfriAur (9 commits)")

---

Tags

edge-computingfirewall-traversaliiotindustrial-automationindustry-4-0nat-traversalopc-uaopcuaopcua-clientphpreverse-connectreverse-helloedgeopcuaopc-uaindustrialIIoTindustry-4.0reverse-connectreversehellonat-traversal

###  Code Quality

TestsPest

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/php-opcua-opcua-client-ext-reverse-connect/health.svg)

```
[![Health](https://phpackages.com/badges/php-opcua-opcua-client-ext-reverse-connect/health.svg)](https://phpackages.com/packages/php-opcua-opcua-client-ext-reverse-connect)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[symfony/mailer

Helps sending emails

1.6k409.1M1.5k](/packages/symfony-mailer)[php-opcua/opcua-client

Pure PHP OPC UA client — binary protocol over TCP, 6 security policies, browse/read/write/subscribe/history, zero external dependencies

131.4k23](/packages/php-opcua-opcua-client)[phpro/soap-client

A general purpose SoapClient library

8896.1M54](/packages/phpro-soap-client)[web-auth/webauthn-lib

FIDO2/Webauthn Support For PHP

12510.5M141](/packages/web-auth-webauthn-lib)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M600](/packages/shopware-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
