apache / apache/plc4x

[Feature Request]: Secure ADS with Beckhoff ADS PLC

Open
#2,173 14 comments 0 reactions 0 assignees View on GitHub
ADS java
Dominant language
Java
Stars
1.7k
Forks
504
Avg merge
10h 55m
Merged PRs (30d)
43

Description

### What happened?

Setup or own a Beckhoff/BSD PLC. For Testing you can Download the .iso from Official Beckhoff Website. Setup in Combination with VirtualBox with the following Script in Linux. Load a sample Beckhoff Project with TWINCat
```bash
#!/usr/bin/env bash
#
# create_tcbsd_vm.sh
# Erstellt eine VirtualBox-VM für TwinCAT BSD unter Linux/macOS
# (getestet mit VirtualBox ≥ 6.1)
#

set -euo pipefail

# ‑-- Standardwerte ‑--------------------------------------
TCBSD_ISO_DEFAULT="TCBSD-x64-14-203719.iso"
VBOX_PATH_DEFAULT="$(command -v VBoxManage || true)"

# ‑-- Hilfsfunktionen ‑------------------------------------
usage() {
cat < [-i ] [-p ]

-n Name der Virtuellen Maschine (erforderlich)
-i TwinCAT-BSD-Abbild (ISO/IMG); Standard: ${TCBSD_ISO_DEFAULT}
-p Pfad zu VBoxManage; Standard: automatisch ermittelt

Beispiel:
$0 -n TcBSD-VM
EOF
exit 1
}

ask_yes_no() {
local prompt="$1"
read -rp "$prompt [Y/N] " answer
[[ "${answer^^}" == "Y" ]]
}

err() { echo "Fehler: $*" >&2; exit 1; }

# ‑-- Argumente auswerten ‑------------------------------
VM_NAME=""
TCBSD_ISO="$TCBSD_ISO_DEFAULT"
VBOX_PATH="$VBOX_PATH_DEFAULT"

while getopts ":n:i:p:h" opt; do
case "$opt" in
n) VM_NAME="$OPTARG" ;;
i) TCBSD_ISO="$OPTARG" ;;
p) VBOX_PATH="$OPTARG" ;;
h|*) usage ;;
esac
done

[[ -z "$VM_NAME" ]] && usage
[[ -z "$VBOX_PATH" ]] && err "VBoxManage konnte nicht gefunden werden. Geben Sie den Pfad mit -p an."

WORK_DIR="$(pwd)"
VMDIR="${WORK_DIR}/${VM_NAME}"
INSTALLER_VDI="${VMDIR}/TcBSD_installer.vdi"
RUNTIME_VHD="${VMDIR}/TcBSD.vhd"

echo "Arbeitsverzeichnis: $WORK_DIR"
echo "VM-Name: $VM_NAME"
echo "TwinCAT-Abbild: $TCBSD_ISO"
echo "VBoxManage: $VBOX_PATH"
echo

# ‑-- VirtualBox prüfen / ggf. installieren ‑-------------
if [[ ! -x "$VBOX_PATH" ]]; then
echo "VirtualBox wurde nicht gefunden: $VBOX_PATH"
if ask_yes_no "Möchten Sie VirtualBox jetzt installieren?"; then
if command -v apt-get &>/dev/null; then
sudo apt-get update
sudo apt-get install virtualbox
elif command -v dnf &>/dev/null; then
sudo dnf install VirtualBox
else
err "Automatische Installation wird auf diesem System nicht unterstützt."
fi
VBOX_PATH="$(command -v VBoxManage)"
else
err "Abbruch: Bitte VirtualBox manuell installieren."
fi
fi

# ‑-- ISO-Datei vorhanden? ‑------------------------------
if [[ ! -f "$TCBSD_ISO" ]]; then
echo "TwinCAT-ISO $TCBSD_ISO nicht gefunden."
echo "Bitte von der Beckhoff-Website herunterladen und ins aktuelle Verzeichnis kopieren."
echo "Download-Seite wird geöffnet …"
xdg-open "https://www.beckhoff.com/de-de/produkte/ipc/software-and-tools/operating-systems/c9900-s60x-cxxxxx-0185.html" &>/dev/null || true
exit 1
fi

# ‑-- VM anlegen ‑----------------------------------------
echo "Erstelle Virtuelle Maschine '$VM_NAME' …"
"$VBOX_PATH" createvm --name "$VM_NAME" \
--basefolder "$WORK_DIR" \
--ostype FreeBSD_64 --register

"$VBOX_PATH" modifyvm "$VM_NAME" \
--memory 1024 --vram 128 \
--acpi on --hpet on \
--graphicscontroller vmsvga \
--firmware efi64

# ‑-- Abbild konvertieren ‑------------------------------
echo "Konvertiere Installations-Abbild → VDI …"
mkdir -p "$VMDIR"
"$VBOX_PATH" convertfromraw --format VDI "$TCBSD_ISO" "$INSTALLER_VDI"

# ‑-- SATA-Controller & Medien einrichten ‑---------------
echo "Erstelle SATA-Controller …"
"$VBOX_PATH" storagectl "$VM_NAME" \
--name SATA --add sata --controller IntelAhci \
--hostiocache on --bootable on

echo "Binde Installer-VDI an Port 1 …"
"$VBOX_PATH" storageattach "$VM_NAME" \
--storagectl SATA --port 1 --device 0 --type hdd --medium "$INSTALLER_VDI"

echo "Erstelle leere System-Festplatte (4 GiB VHD) …"
"$VBOX_PATH" createmedium --filename "$RUNTIME_VHD" --size 4096 --format VHD

echo "Binde System-Festplatte an Port 0 …"
"$VBOX_PATH" storageattach "$VM_NAME" \
--storagectl SATA --port 0 --device 0 --type hdd --medium "$RUNTIME_VHD"

# ‑-- VM starten ‑---------------------------------------
echo
echo "Starte die VM – folgen Sie den TwinCAT-BSD-Installationsschritten."
"$VBOX_PATH" startvm "$VM_NAME" --type gui

echo "Fertig."
```
Run Example Code:

```java

import org.apache.plc4x.java.api.PlcConnection;
import org.apache.plc4x.java.api.PlcDriverManager;
import org.apache.plc4x.java.api.authentication.PlcUsernamePasswordAuthentication;
import org.apache.plc4x.java.api.messages.PlcReadRequest;
import org.apache.plc4x.java.api.messages.PlcReadResponse;

import java.util.concurrent.TimeUnit;

public class AdsDemo {
public static void main(String[] args) throws Exception {

String connectionString =
"ads:tcp://192.168.1.120:8016?" +
"target-ams-net-id=192.168.1.120.1.1&target-ams-port=851&" +
"source-ams-net-id=192.168.1.233.1.1&source-ams-port=32905";

PlcUsernamePasswordAuthentication authentication = new PlcUsernamePasswordAuthentication("Administrator", "2");
try (PlcConnection plcConnection = PlcDriverManager.getDefault().getConnectionManager().getConnection(connectionString, authentication)) {

// Build a read request (PLC4J-0.12 uses addTag; addItem also works)
PlcReadRequest readReq = plcConnection.readRequestBuilder()
.addTagAddress("nbool", "MAIN.nbool") // or %MX0.0:BOOL
.addTagAddress("nint", "MAIN.nCounter")
.build();

PlcReadResponse resp = readReq.execute().get(3, TimeUnit.SECONDS);
boolean flag = resp.getBoolean("nbool");
System.out.println("MAIN.nbool = " + flag);
int counter = resp.getInteger("nint");
System.out.println("MAIN.nCounter = " + counter);
}

}
}
```

Route gets Created:

Image

Error During Runtime if unsecure Port is disabled in firewall like its default for the BSD version of Twincat.

Image

For further Information simply Ask.

with regards

### Version

v0.12.0

### Programming Languages

- [ ] plc4c
- [ ] plc4go
- [x] plc4j
- [ ] plc4net
- [ ] plc4py

### Protocols

- [ ] AB-Ethernet
- [x] ADS /AMS
- [ ] BACnet/IP
- [ ] C-Bus
- [ ] CANopen
- [ ] EtherNet/IP
- [ ] Firmata
- [ ] IEC-69870
- [ ] KNXnet/IP
- [ ] Modbus
- [ ] OPC-UA
- [ ] Profinet
- [ ] S7
- [ ] S7-light

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the PLC4J AdsDemo connection against the Beckhoff/TwinCAT BSD setup described in the issue, with the unsecure port disabled. Review the ADS/AMS connection options and authentication path shown in the Java example. Done means a secure ADS connection can be established and the example read request succeeds without relying on the disabled unsecure port.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.