PLC4X Server
The PLC4X Server is a small relay server that speaks the PLC4X proxy protocol.
A client using the plc4x driver connects to this server, and the server opens the real connection to a PLC on its behalf and forwards reads and writes.
This is useful when the PLCs are only reachable from the machine running the server (e.g. behind a firewall or on an isolated OT network), while the clients live elsewhere.
+------------+ plc4x proxy protocol +--------------+ native protocol +-------+ | client | ------------------------> | PLC4X Server | ------------------> | PLC | | (plc4x drv)| TLS + auth | | (s7, modbus, …) | | +------------+ +--------------+ +-------+
The server bundles all PLC4X drivers, so the relayed connection string can target any supported protocol (s7, modbus, ads, opcua, simulated, …).
Security model
-
Authentication is mandatory. Every client connection must complete a username/password handshake before any operation is accepted. There is no unauthenticated mode.
-
TLS is the default transport. Credentials and payloads are encrypted in transit. Plaintext TCP is available only as an explicit opt-in for trusted networks/testing.
Building
From the module directory:
mvn package
This produces a runnable fat-jar at target/plc4j-plc4x-server-<version>.jar.
Running the server
java -jar target/plc4j-plc4x-server-<version>.jar [port]
The listen port may be given as the first argument, or via the plc4x.server.port system property / PLC4X_SERVER_PORT environment variable. If omitted it defaults to 59837.
First start with no configuration
If you start the server without configuring credentials, it generates a default identity and prints it once to the console:
============================================================ No PLC4X server credentials configured - generated defaults: username: toddy password: 3Qm0v2yq... (randomly generated) Provide plc4x.server.username/password to set your own. ============================================================
Because no keystore is configured either, it also generates an ephemeral self-signed TLS certificate and logs its fingerprint so a client can trust/pin it:
No keystore configured - generated an ephemeral self-signed certificate. Server certificate SHA-256 fingerprint: B1:A5:51:F8:...:35:CE
| Configured credentials are never logged — only generated ones are printed. |
Configuration
All settings are read from system properties (-D…) or environment variables.
| Setting | System property | Environment variable | Default |
|---|---|---|---|
Listen port |
|
|
|
Username |
|
|
|
Password |
|
|
(generated) |
Plaintext mode |
|
|
|
TLS keystore |
|
— |
(self-signed) |
Keystore pass. |
|
— |
— |
Example: explicit credentials + your own TLS certificate
java \
-Dplc4x.server.port=59837 \
-Dplc4x.server.username=operator \
-Dplc4x.server.password='s3cr3t!' \
-Dplc4x.server.keystore=/etc/plc4x/server.p12 \
-Dplc4x.server.keystore-password='keystorepass' \
-jar target/plc4j-plc4x-server-<version>.jar
The keystore must be a PKCS12 (or JKS) file containing the server’s private key and certificate.
Connecting a client
A client uses the plc4x driver. The connection string points at the server, and the remote-connection-string parameter (URL-encoded) tells the server which PLC to open.
Connection string format
plc4x:<transport>://<server-host>:<server-port>?remote-connection-string=<url-encoded-plc-url>&username=<user>&password=<pass>[&tls.verify-ssl=false]
-
<transport>istls(default) ortcp(plaintext).plc4x://…without a prefix uses the default, TLS. -
remote-connection-stringis the URL-encoded connection string the server should open to the actual PLC. -
username/passwordare mandatory. -
tls.verify-ssl=falsedisables certificate validation — needed when the server uses an auto-generated self-signed certificate. With a properly trusted (CA-signed) certificate, leave it at its default (true).
Example (Java)
Target PLC URL s7://10.10.1.5 → URL-encoded as s7%3A%2F%2F10.10.1.5.
String url = "plc4x:tls://server.example.com:59837"
+ "?remote-connection-string=s7%3A%2F%2F10.10.1.5"
+ "&username=operator"
+ "&password=s3cr3t!"
+ "&tls.verify-ssl=false"; // self-signed server cert
try (PlcConnection connection = new DefaultPlcDriverManager().getConnection(url)) {
PlcReadRequest request = connection.readRequestBuilder()
.addTagAddress("value", "%DB1.DBW0:INT")
.build();
PlcReadResponse response = request.execute().get();
System.out.println(response.getInteger("value"));
}
Troubleshooting
| Symptom | Cause / fix |
|---|---|
|
TLS cert not trusted by the client. Add |
Connect fails with |
Missing or wrong |
Connect hangs or fails immediately on a |
Transport mismatch — client and server must agree on TLS vs plaintext. |
|
The server could not open the |