matsab.de

SIMATIC IOT2040 mit macOS

Diese Anleitung beschreibt wie man unter macOS das SIMATIC IOT2040 installiert und einrichtet. MacOS bringt bereits alles was dazu benötigt wird mit, es muss keine weitere Software auf dem Mac installiert werden. 

Image auf SD-Karte schreiben

1. Benötigt wird ein Betriebssystem-Abbild (Image) des IOT2040 welches hier heruntergeladen werden kann: Simatic Forum
Zum Zeitpunkt dieser Anleitung nennt sich das Image “Example_Image_V2_1_3.zip”. Die ZIP-Datei speichert man am besten in einem eigenen Ordner auf dem Mac ab und entpackt sie dort per doppelklick. Das eigentliche Image nennt sich “example-V2.1.3.wic

2. SD-Karte in den Kartenleser des Mac einstecken

3. Terminal auf dem Mac öffnen, in das Downloadverzeichnis des Images wechseln und folgendes Kommando ausführen:

diskutil list

4. In der Ausgabeliste muss nun das SD-Karten-Laufwerk identifiziert werden. Hier im Beispiel ist die SD-Karte anhand des Windows FAT32 Dateisystems und anhand der Datenträgergröße von 16GB zu erkennen. Ebenso kann der Name der SD-Karte herangezogen werden (Hier: “No Name”). Wichtig ist das Laufwerk zu wählen (z.B. disk2), keine Partition (disk2s1)

/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *1.0 TB     disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:                  Apple_HFS Macintosh HD            999.9 GB   disk0s2

/dev/disk1 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *512.1 GB   disk1
   1:                        EFI EFI                     209.7 MB   disk1s1
   2:                  Apple_HFS Macintosh SSD           511.1 GB   disk1s2
   3:                 Apple_Boot Recovery HD             650.0 MB   disk1s3

/dev/disk2 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *15.9 GB    disk2
   1:             Windows_FAT_32 NO NAME                 15.9 GB    disk2s1

5. SD-Karte auswerfen (unmounten) dazu wird der disk identifier aus Schritt 4 gebraucht:

diskutil unmountDisk /dev/disk2

6. Zum Schreiben des Images auf die SD-Karte wird das Kommando dd benutzt, welches die Parameter BlockSize (bs), InputFile (if) und OutputFile (of) übergeben bekommt. Als InputFile wird der Name der Image-Datei angegeben, als OutputFile das SD-Kartenlaufwerk.

Zu Beachten ist, das nicht der “normale” Diskname benutzt wird, sondern der Diskname mit vorgestelltem “r” (für RawDisk):

sudo dd bs=1m if=example-V2.1.3.wic of=/dev/rdisk2

Nach Eingabe des Administrator Kennworts wird das Image auf die SD-Karte geschrieben. Eine Ausgabe erfolgt jedoch erst, nachdem das vollständige Image geschrieben wurde. Dies kann je nach Geschwindigkeit der SD-Karte ein paar Minuten dauern. Bei erfolgreichem Abschluss sollte eine Ausgabe erfolgen:

1041+1 records in
1041+1 records out
1092491264 bytes transferred in 115.502149 secs (9458623 bytes/sec)

Wer auf dem Mac keinen Treiber für EXT Filesysteme installiert hat, bekommt im Anschluss eine Fehlermeldung das die SD-Karte nicht gemountet werden konnte:

“Auswerfen” quittiert die Fehlermeldung und die SD-Karte kann aus dem Kartenleser entnommen werden.

7. Die SD-Karte kann nun in den IOT2040 eingesetzt werden. Fertig!

Ersteinrichtung des IOT2040

1. Das Image des IOT2040 hat auf der ersten Netzwerkkarte die feste IP-Adresse 192.168.200.1 mit der Netzmaske 255.255.255.0 vergeben. Um sich vom Mac aus zum ersten Mal mit dem IOT2040 zu verbinden, muss sich der Mac im selben Netzwerk befinden. Am besten vergibt man dazu ebenfalls eine feste Netzwerkadresse. Hier im Beispiel ist das einfach die 192.168.200.2 (Systemeinstellungen/Netzwerk):

2. Im Terminal des Mac kann man sich nun per ssh auf dem IOT2040 einloggen:

ssh root@192.168.200.1

3. Man befindet sich nun in der Shell des IOT2040. Hier sollten ein paar grundlegende Einstellungen gemacht werden. Am einfachsten geht das mit Hilfe des iot2000setup programms:

iot2000setup

Mindestens die folgenden 3 Menüpunkte sollte man ausführen:

Expand File System vergrößert das Dateisystem auf die komplette verfügbare Kapazität der SD-Karte.

Change Root Password ist hier der wichtigste Punkt: Man sollte niemals einen Zugang zu einem Rechner ohne Passwort betreiben. Hier muss unbedingt ein Passwort vergeben werden, selbst wenn der IOT2040 nur zum “spielen” benutzt wird. Man sollte daran denken, der IOT2040 befindet im Netzwerk und ggf. sogar im Heimnetzwerk.

Configure Network Interfaces erlaubt es die vorkonfigurierte feste IP Adresse des IOT2040 zu ändern oder DHCP zu aktivieren. 

Security: Zugang via SSH private/public key

SSH erlaubt einen viel sichereren Weg um sich Einzuloggen als mit Benutzername und Passwort: der Login anhand eines private und public key Verfahrens. Im Gegensatz zu einem Passwort lässt sich dieses Verfahren nicht durch brute force Attacken knacken.

Es wird ein privater und ein öffentlicher Schlüssel generiert, der öffentliche Schlüssel wird dann auf den IOT2040 (SSH Server) übertragen. Ein Client Rechner der sich zum IOT2040 verbinden möchte, benötigt dann den dazugehörigen privaten Schlüssel. Erst wenn beide Schlüssel zusammenpassen wird der Login durchgeführt.

Um die Sicherheit noch weiter zu erhöhen, kann eine Passphrase beim Zugriff auf den privaten Schlüssel (auf dem Client Rechner) vergeben werden. Dies verhindert dann, dass ein Unberechtigter Dritter, der Zugriff auf den Client Rechner hat, auch SSH Zugang zum IOT2040 bekommt.

1. Im Terminal des Mac (des Client Rechners) wird zunächst das Schlüsselpaar, bestehend aus private und public key, erzeugt:

ssh-keygen -t rsa

Ein paar Fragen zum Erzeugen der Schlüssel müssen noch beantwortet werden (diese können mit Return bestätigt werden) und die Schlüssel werden erstellt:

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/mats/.ssh/id_rsa):
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/mats/id_rsa.
Your public key has been saved in /Users/mats/id_rsa.pub.
The key fingerprint is:
SHA256:L3eOGZnjJ/Tak7279IznZJ0Vu4YKItI2QAdyA/HGzZU
The key's randomart image is:
+---[RSA 2048]----+
| +o+   ..        |
|  = = .E         |
|   = +         . |
|  o .           o|
|   .    S      ..|
|    o    ..o  . =|
|   . = ..oB..+.++|
|    o o .+oO*.o*.|
|          ==o.=*+|
+----[SHA256]-----+

2. Public Key vom Mac auf den IOT2040 kopieren (192.168.78.32 ist die geänderte IP-Adresse des IOT2040):

ssh-copy-id root@192.168.78.32 

Es sollte nun eine Ausgabe erfolgen das der entsprechende public key übertragen wurde. Wer das root Passwort wie oben beschrieben geändert hat, muss es hier natürlich zur Übertragung des Schlüssels eingeben.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: „~/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.78.32's password: 

Number of key(s) added:        1

Now try logging into the machine, with:   "ssh 'root@192.168.78.32'"
and check to make sure that only the key(s) you wanted were added.

3. Wenn alles geklappt hat sollte man sich jetzt ohne Passworteingabe auf dem IOT2040 einloggen können:

ssh root@192.168.78.32

4. Ab jetzt kann auf dem IOT2040 ein SSH Zugang per Passwort komplett abgeschaltet werden:

nano /etc/ssh/sshd_config

Folgende Einträge sollten hier in der SSH Konfigurationsdatei gesetzt werden, alle anderen können gefahrlos auskommentiert werden (durch voranstellen von #): 

Protocol 2
PermitRootLogin without-password
PubkeyAuthentication yes
ChallengeResponseAuthentication no
PasswordAuthentication no
AddressFamily inet

Protocol 2 SSH Protokoll Version 2 soll benutzt werden.

PermitRootLogin mit der Einstellung without-password ist dabei etwas missverständlich. Es ermöglicht root logins, aber nur wenn die Authentifizierungmethode eine andere als Passwort war.

PubkeyAuthentication yes Authentifizierung mittels public key aktivieren

ChallengeResponseAuthentication no Diese Authentifizierung fragt ebenfalls nach einem Passwort, deshalb abschalten

PasswordAuthentication no Authentifizierung mittels Passwort abschalten

AddressFamily inet erlaubt SSH nur mit dem Protokoll IPV4 und nicht etwa via IPV6.

5. Neustart des IOT2040 durchführen (via „Reboot“) oder nur den SSH Daemon neu starten damit die Änderungen wirksam werden:

/etc/init.d/sshd restart

Security: IPV6 abschalten

Beim Thema Sicherheit ist es immer eine gute Idee alles was nicht benötigt wird abzuschalten. Die wenigsten benutzen bei ihren lokalen Netzwerken schon IPV6. Speziell im Hausgebrauch dominiert immer noch IPV4.

Da beim vorherigen Punkt “SSH Zugang mit private und public key”, der Zugang schon auf IPV4 beschränkt wurde, kann IPV6 auch komplett deaktiviert werden. Die Netzwerk Adapter des IOT2040 bekommen dann auch keine IPV6 Adresse mehr zugewiesen falls man DHCP aktiviert hat. 

Zum Ausschalten von IPV6 muss dazu eine Konfigurationsdatei angepasst werden:

nano /etc/sysctl.conf

Folgende Parameter eintragen:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Security: Firewall konfigurieren

Gerade beim Thema IOT (Internet Of Things) sollte Sicherheit an vorderster Stelle stehen. Dazu gehört, alles was nicht gebraucht wird abzuschalten und alles was gebraucht wird, entsprechend abzusichern. In jedem Fall gehört eine Firewall dazu.

Der Kernel des auf dem IOT2040 installierten Linux hat bereits eine integrierte Firewall. Diese Firewall kann mit Hilfe der Anwendung iptables konfiguriert werden. Iptables unterstützt vielfältige Paketmanipulationen, Paketfilterung und Network Adress Translation (NAT).

Iptables nutzt Filterketten (chains) um Netzwerkpakete zu verarbeiten. Es existieren drei Standard Filterketten INPUT (für eingehende Pakete), FORWARD (für weiterzuleitende Pakete) und OUTPUT (für Pakete die vom IOT2040 ausgehend sind). 

1. Um sich die aktuell aktiven Firewall Regeln anzuschauen gibt man folgendes ein:

iptables -L

In der Ausgabe sind die drei (noch leeren) Filterketten zu sehen. In dieser Konfiguration werden keine Pakete gefiltert, die Firewall ist sozusagen ausgeschaltet:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

2. Bevor man Firewall Regeln definiert, sollte man wissen welche Ports überhaupt auf dem IOT2040 geöffnet sind. Diese kann man sich mit folgendem Kommando anzeigen lassen:

netstat -tuln

Die Ausgabe sollte in etwa wie folgt aussehen:

Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:1534            0.0.0.0:*               LISTEN      
udp        0      0 0.0.0.0:1534            0.0.0.0:*                          

Hier sieht man die offenen Ports 22 (genutzt von SSH) und 1534 der zum vorinstallierten TCF-Agent gehört. TCF steht für Target Communication Framework, welches dazu dient, Applikationen auf dem IOT2040 zu debuggen, profilen und patchen. Auf einem Produktivsystem ist letzteres sicher nicht erwünscht.

2a. Wer kein Remote Debugging mit Eclipse machen will, kann den TCF-Agent wie folgt stoppen:

/etc/init.d/tcf-agent stop

Und so verhindert man, das der TCF-Agent beim Systemstart automatisch gestartet wird:

update-rc.d -f tcf-agent remove

3. Iptables kann eingegebene Regeln unmittelbar und sofort “scharf schalten”. Beim Neustart des IOT2040 sind diese Regeln jedoch verloren. Es empfiehlt sich daher, die Firewall Regeln in einer Datei abzuspeichern (der Name der Datei ist beliebig, hier wird “iptables.up.rules” benutzt):

nano /etc/iptables.up.rules

Es gibt zwei Herangehensweisen für Regeln:
Alles was nicht verboten ist, ist erlaubt ODER Alles was nicht erlaubt ist, ist verboten.

Die sicherere Variante ist Alles was nicht erlaubt ist, ist verboten. Folgende Basisregeln erlauben eingehende Verbindungen nur für SSH und den Ping Befehl, alle anderen werden verworfen. Ausgehende Verbindungen werden als sicher erachtet und sollen erlaubt sein:

*filter

# Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT

# Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allows SSH connections
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# Reject all other inbound - default deny unless explicitly allowed policy:
-A INPUT -j REJECT
-A FORWARD -j REJECT

# Allows all outbound traffic
-A OUTPUT -j ACCEPT

COMMIT

4. Nach dem Speichern der Regeln können diese wie folgt aktiviert werden:

iptables-restore < /etc/iptables.up.rules

Die neuen Regeln können nun erneut durch Eingabe von iptables -L angeschaut werden:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             127.0.0.0/8          reject-with icmp-port-unreachable
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere        

5. Um diese Regeln nun auch nach einem Neustart des IOT2040 zu aktivieren, ist noch ein Skript zu Erstellen, das vor dem Aktivieren der Netzwerkschnittstellen aufgerufen wird:

nano /etc/network/if-pre-up.d/iptables

Das Skript beinhaltet nur den Restore Befehl zum Aktivieren der Firewall Regeln wie schon unter Punkt 4 beschrieben:

#!/bin/sh
/usr/sbin/iptables-restore < /etc/iptables.up.rules

Damit das Skript auch ausgeführt werden kann, müssen noch die Rechte entsprechend gesetzt werden:

chmod +x /etc/network/if-pre-up.d/iptables

Farbige Shell aktivieren

Wer viel auf der Kommandozeile arbeitet oder es einfach ein wenig bunter mag, kann die Farbunterstützung der Bash aktivieren:

Dazu müssen zwei bereits auf dem IOT2040 befindliche Dateien ins Homeverzeichnis kopiert werden:

cp /etc/skel/.profile ~/

cp /etc/skel/.bashrc ~/

Der Inhalt der Datei “.bashrc” muss dann noch durch folgenden Inhalt ersetzt werden:

 # ~/.bashrc: executed by bash(1) for non-login shells.

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
        # We have color support; assume it's compliant with Ecma-48
        # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
        # a case would tend to support setf rather than setaf.)
        color_prompt=yes
    else
        color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '
else
    PS1='\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# some more ls aliases
alias ll='ls -la'
#alias la='ls -A'
#alias l='ls -CF'