Troubleshooting Siemens IOT2020 DNS Resolution on Static IP
The Siemens SIMATIC IOT2020 (6ES7647-0AA00-0YA2) and IOT2040 (6ES7647-0AA00-1YA2) are Intel Quark x1000-based industrial IoT gateways designed to bridge field-level PLC networks with higher-level MES, cloud, or analytics systems. Both ship with the Siemens "Example Image" based on Debian 8 (jessie) and the proprietary iot2000setup console tool that drives first-boot configuration through a serial terminal. A recurring field issue with these devices is that name resolution (DNS) works correctly under DHCP, but the moment a fixed / static IPv4 address is configured through iot2000setup, hostnames stop resolving and any application that depends on FQDN lookup (NTP, OPC UA, MQTT brokers, cloud SDKs, package updates) silently fails. This reference documents the root cause, the proven fix used by integrators in the field, and the verification steps that confirm DNS is genuinely restored rather than merely masked.
Affected Hardware, Firmware, and Image Revisions
| Model | Order Number | SoC | RAM | Example Image Branch | Symptom Reproducible |
|---|---|---|---|---|---|
| SIMATIC IOT2020 | 6ES7647-0AA00-0YA2 | Intel Quark x1000 @ 400 MHz | 1 GB DDR3 | Debian 8 / kernel 4.4 | Yes |
| SIMATIC IOT2040 | 6ES7647-0AA00-1YA2 | Intel Quark x1000 @ 400 MHz | 1 GB DDR3 | Debian 8 / kernel 4.4 | Yes |
| SIMATIC IOT2050 | 6ES7647-0BA00-0YA2 | ARM Cortex-A53 quad-core | 1 GB / 2 GB DDR4 | Debian 10 / kernel 5.10 | Different mechanism (see Notes) |
The behavior described in this article is specific to the IOT2020/IOT2040 Example Image where iot2000setup writes /etc/network/interfaces directly and where resolvconf may or may not be installed depending on the exact point release. The IOT2050 uses a fundamentally different image and systemd-resolved; the manual /etc/resolv.conf edit pattern still works there but is not the canonical procedure.
Problem Statement
The fault pattern observed in the field is consistent across deployments:
- The IOT2020 is configured through
iot2000setupwith DHCP. After reboot,ping 8.8.8.8succeeds andping google.comalso succeeds. DNS resolution works. - The administrator reconfigures the device with a fixed IP address, subnet mask, and gateway through the same tool (or by editing
/etc/network/interfacesdirectly). - After reboot,
ping 8.8.8.8still succeeds (Layer 3 is fine) butping google.comfails withping: unknown host google.com. The same behavior applies to every FQDN-based service the gateway runs. - Re-entering DHCP through
iot2000setupimmediately restores DNS. Re-entering a fixed IP breaks it again.
The output of cat /etc/resolv.conf after the failure typically shows either an empty file, a file containing only the literal word nameserver with no address, or a stale DHCP lease value that points at a server that no longer accepts the static client. The /etc/network/interfaces file may contain correct dns-nameservers directives, but those directives are silently ignored because resolvconf is not installed on the standard image and the ifupdown hooks have nobody to talk to.
Root Cause: Why DNS Stops Working After Static IP Configuration
The Example Image used by Siemens relies on the legacy Debian ifupdown network stack. The chain that should populate /etc/resolv.conf looks like this:
-
ifup eth0parses/etc/network/interfaces. - If
dns-nameservers 8.8.8.8 8.8.4.4is present and theresolvconfpackage is installed,ifupdownpasses the values toresolvconf, which atomically regenerates/etc/resolv.conf. - If
resolvconfis not installed (default on the stock Example Image),ifupdownsimply drops the directives and the file/etc/resolv.confis never updated.
Under DHCP, the dhclient daemon writes /etc/resolv.conf directly via its resolv.conf hook script (/etc/dhcp/dhclient-exit-hooks.d/resolvconf or its fallback), which is why DNS appears to "work" only in DHCP mode. When the static configuration is written by iot2000setup, dhclient is no longer run, the hook is never executed, and no other component regenerates the resolver file.
A second failure mode compounds the issue: /etc/resolv.conf on the IOT2020 is sometimes a symlink to /var/run/resolvconf/resolv.conf. If resolvconf was never installed, that target file does not exist and the symlink dangles. Any attempt to overwrite the symlink target then writes to a non-existent path, leaving the operator convinced that the change "did not take".
dns-nameservers lines to /etc/network/interfaces alone will not work on the stock IOT2020 image. You must either install resolvconf, replace the symlink manually, or hard-write the resolver file and protect it against being clobbered on next boot.
Solution: Rebuild and Lock /etc/resolv.conf
The integrated procedure that resolves the issue on the IOT2020 / IOT2040 Example Image is the one documented in the original Siemens support thread and replicated by Siemens support engineers. It has three parts, all of which are required for a permanent fix.
Step 1 — Remove the stale /etc/resolv.conf
Connect to the IOT2020 either over the serial console (115200 8N1) or over SSH. Become root:
su -
Inspect the current file and its inode:
ls -l /etc/resolv.conf
stat /etc/resolv.conf
If it is a symlink (which is the most common state on a stock image), unlink it:
unlink /etc/resolv.conf
If it is a regular file that was zeroed out by a failed DHCP attempt, delete it outright:
rm -f /etc/resolv.conf
Step 2 — Write a fresh resolver file
Create a new /etc/resolv.conf with one or more valid upstream resolvers. Use the gateway IP (most reliable when on a routed corporate subnet) and a public fallback such as Google's 8.8.8.8 / 8.8.4.4 or Cloudflare's 1.1.1.1:
cat > /etc/resolv.conf <<'EOF'
# Generated manually for static-IP deployment
nameserver 192.168.1.1
nameserver 8.8.8.8
nameserver 1.1.1.1
search example.local
EOF
The search directive is optional but recommended when the IOT2020 needs to reach PLCs by short hostname (e.g. s7-1500 instead of s7-1500.plant.example.local). Use the DNS suffix your control network actually publishes; do not invent one.
Lock the permissions so the file is not silently overwritten by a misbehaving service:
chmod 644 /etc/resolv.conf
chown root:root /etc/resolv.conf
Step 3 — Make the file immutable
This is the step that prevents recurrence after reboot. The chattr +i flag tells the kernel to reject any write to the file, including writes from dhclient hooks, ifupdown scripts, or stray apt post-install hooks:
chattr +i /etc/resolv.conf
Verify the immutable bit is set:
lsattr /etc/resolv.conf
# expected output line: ----i---------e----- /etc/resolv.conf
If you ever need to edit the file later (for example to switch upstream resolvers), drop the immutable bit first:
chattr -i /etc/resolv.conf
nano /etc/resolv.conf
chattr +i /etc/resolv.conf
resolvconf and certain DHCP client upgrades) will refuse to proceed if /etc/resolv.conf is immutable. Plan to lift the bit, install the package, then re-apply chattr +i.
Verification Procedure
Run the following checks in order. Each one isolates a different layer of the resolver path.
-
Resolver file present and immutable:
ls -l /etc/resolv.conf && lsattr /etc/resolv.conf
Expected: regular file owned by root,----i---------e-----flag set. -
Layer 3 reachability:
ping -c 3 8.8.8.8
Expected: at least one reply. If this fails the gateway is the issue, not DNS. -
Direct DNS query against each configured resolver:
dig @8.8.8.8 google.com +short
Expected: at least one A record. If dig is not installed,apt-get install dnsutilsfirst. -
Resolver library path:
getent hosts google.com
Expected: prints the IP address. This exerciseslibc→/etc/nsswitch.conf→/etc/resolv.confend to end. -
Application-level probe:
curl -v https://www.siemens.com --max-time 10 -o /dev/null
Expected: TLS handshake completes. If this fails but step 4 succeeds, suspect a transparent proxy, MTU, or TLS interception device on the corporate network. -
Persistence after reboot:
rebootand re-run steps 1 and 4 from a fresh SSH session. If DNS breaks again, the immutable bit was not honored (typically because the filesystem was remounted or the file was recreated by an init script).
Persistent Configuration Through /etc/network/interfaces
For deployments that prefer to keep all network state in one declarative file, install the resolvconf package so that ifupdown can update the resolver file automatically when the interface comes up:
apt-get update
apt-get install resolvconf
Then add the DNS directives to /etc/network/interfaces inside the iface eth0 inet static stanza:
auto eth0
iface eth0 inet static
address 192.168.1.50
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 192.168.1.1 8.8.8.8 1.1.1.1
dns-search example.local
Reboot, then verify:
ls -l /etc/resolv.conf
# Expected: /etc/resolv.conf -> /var/run/resolvconf/resolv.conf
cat /etc/resolv.conf
Apply the immutable bit to the underlying target file so that downstream hooks cannot clobber it:
chattr +i /var/run/resolvconf/resolv.conf
Alternative: Disabling Network Manager Overrides
On later Example Image point releases (V2.6 and above), Siemens introduced NetworkManager alongside ifupdown. NetworkManager owns /etc/resolv.conf via its own dispatcher and will overwrite the file you manually wrote if it believes it has authority over the interface. To keep the manual file in place:
systemctl stop NetworkManager
systemctl disable NetworkManager
Then re-apply the immutable bit and reboot. This approach is acceptable on a single-ethernet device that is permanently wired into one control VLAN, which is the typical IOT2020 deployment topology.
Edge Cases: Corporate Proxies, IPv6, and Split DNS
| Scenario | Symptom | Diagnosis | Remediation |
|---|---|---|---|
| Corporate transparent proxy on port 3128 | DNS works, HTTPS fails with 407 |
env | grep -i proxy shows nothing; curl -v shows CONNECT 407 |
Set http_proxy / https_proxy in /etc/environment or per-service |
| Split-horizon DNS with two internal zones | Public DNS works, internal PLC hostnames fail |
dig plc01.corp.local @192.168.1.1 returns NXDOMAIN from gateway, SERVFAIL from public |
Add internal zone as nameserver above public fallback in /etc/resolv.conf
|
| IPv6-only upstream | A queries return NOERROR with empty answer section |
dig AAAA google.com works, dig A google.com returns nothing |
Add options inet6 to /etc/resolv.conf or enable NAT64 / DNS64 upstream |
| Captive portal redirect | DNS works for first 30 s then stops | TCP/53 from gateway is accepted, UDP/53 is rate-limited after handshake | Use TCP-only resolver (nameserver 8.8.8.8 with options use-vc) or switch to DoT (Cloudflare 1.1.1.1:853 via stubby) |
| VLAN tag lost on reboot | IP is correct but gateway unreachable |
ip route shows no default route |
Add vlan-raw-device eth0 and vlan-id 100 to /etc/network/interfaces; reboot |
| DNS resolver behind firewall that blocks UDP/53 | Intermittent timeouts on first query |
dig +tcp succeeds, plain dig times out |
Add options timeout:2 attempts:5 use-vc to force TCP |
Troubleshooting Matrix
| Observed Symptom | Most Likely Cause | First Diagnostic Command | Fix |
|---|---|---|---|
ping by IP works, by name fails |
/etc/resolv.conf empty or stale |
cat /etc/resolv.conf |
Rebuild as in Step 2 of Solution |
| Name works for 10 s, then fails | Captive portal / firewall UDP/53 rate-limit | dig +tcp google.com |
Add options use-vc
|
| Name works on DHCP, fails on static |
resolvconf not installed |
dpkg -l | grep resolvconf |
Install resolvconf or hard-write /etc/resolv.conf
|
| File reverts after reboot | Init script or NetworkManager recreating it | journalctl -b | grep resolv |
Disable NetworkManager; apply chattr +i
|
| Name works, HTTPS handshake fails | Transparent proxy / TLS interception | openssl s_client -connect siemens.com:443 |
Configure https_proxy or install corporate CA bundle |
| All connectivity fails after static config | Wrong subnet mask / no default route | ip route |
Correct /etc/network/interfaces
|
| DNS resolution slow (>2 s per query) | First nameserver unreachable, fallback used |
dig google.com shows long response time on first server |
Reorder or remove dead nameserver entries |
Backup and Rollback Procedure
Before touching /etc/resolv.conf, snapshot the current network state so a broken change can be undone from the serial console:
cp /etc/resolv.conf /etc/resolv.conf.bak
cp /etc/network/interfaces /etc/network/interfaces.bak
cp /etc/nsswitch.conf /etc/nsswitch.conf.bak
Rollback is then a single command from the serial console:
chattr -i /etc/resolv.conf
cp /etc/resolv.conf.bak /etc/resolv.conf
chattr +i /etc/resolv.conf
systemctl restart networking
Frequently Asked Questions
Why does DNS work on DHCP but break the moment I switch to a static IP on the IOT2020?
Under DHCP, the dhclient exit hook writes the upstream resolver addresses into /etc/resolv.conf directly. Under a static IP, ifupdown relies on the resolvconf package to translate the dns-nameservers directive into a resolver file, and resolvconf is not installed on the stock Example Image. The result is a stale or empty /etc/resolv.conf.
Do I have to use Google's 8.8.8.8 as a nameserver, or can I keep my corporate one?
Either works. Put the corporate / gateway resolver first (it usually knows the local zone) and a public fallback such as 8.8.8.8 or 1.1.1.1 second. Three entries is the practical maximum; more than that slows down fallback when the primary is down.
Is the chattr +i step really necessary?
Yes, on the IOT2020 it is. Without the immutable bit, the next reboot, package upgrade, or iot2000setup re-run will silently overwrite /etc/resolv.conf and you will be back to "DNS mysteriously stopped working". Lifting the bit is required before any apt-get install that touches the file.
Does this same procedure apply to the SIMATIC IOT2050?
Mechanically yes, but the IOT2050 ships with systemd-resolved active and the canonical fix is to edit /etc/systemd/resolved.conf (DNS= and Domains= directives) then restart the service. The manual /etc/resolv.conf rebuild still works as a quick field fix when the systemd path is unavailable.
My corporate network uses a proxy. Can I still fix DNS without bypassing it?
Yes. Configure the corporate DNS resolvers (typically the gateway IP or a dedicated internal DNS server) in /etc/resolv.conf exactly as described. The proxy only affects HTTP/HTTPS egress on TCP/3128 or TCP/8080, not DNS on UDP/53 or TCP/53. If the proxy also intercepts DNS, use the proxy's DNS relay address instead of 8.8.8.8.
What is the maximum number of nameserver entries I should put in /etc/resolv.conf?
Three is the practical maximum on the IOT2020. The C library queries them in order with a 5-second timeout and 2 retries by default; a fourth or fifth dead resolver measurably delays the first response and has no real-world benefit over three well-chosen ones.