Networking
The guest has one Ethernet interface. By default it is configured with DHCP; static addresses come from the kernel command line.
| Command line | Default | Meaning |
|---|---|---|
uniapp.ip=A.B.C.D/N | DHCP | address and prefix for the first NIC |
uniapp.gw=A.B.C.D | from DHCP | default route |
uniapp.dns=A.B.C.D | from DHCP | nameserver |
ip=dhcp | (Asterinas only) | run the kernel’s DHCP client instead of the built-in 10.0.2.15/24 |
Under QEMU user-mode networking (-netdev user) DHCP yields 10.0.2.15,
gateway 10.0.2.2 and the DNS forwarder 10.0.2.3; the make run-* targets
rely on that. If DHCP fails, /init falls back to exactly those values.
How the interface is configured
On Linux /init runs a small DHCPv4 client over an AF_PACKET socket
(DISCOVER, OFFER, REQUEST, ACK; five attempts with backoff), then applies
the lease with the classic ioctls SIOCSIFADDR, SIOCSIFNETMASK,
SIOCSIFFLAGS and SIOCADDRT. The interface name is discovered from
/sys/class/net, falling back to eth0.
Asterinas has no AF_PACKET sockets, so there the kernel does DHCP:
ip=dhcp on the command line (the Linux ip= parameter) starts smoltcp’s
DHCPv4 client on eth0 and publishes the lease in /proc/net/dhcp as
eth0 10.0.2.15/24 10.0.2.2 dns 10.0.2.3 (or eth0 pending). /init waits
up to 30 s for that line and takes the nameserver from it; the address and
route are already installed. Without ip=dhcp Asterinas keeps its compiled-in
10.0.2.15/24 via 10.0.2.2, which /init may override with uniapp.ip=:
the set-ioctls work since patch 0003. The log line tells you which path ran:
(kernel dhcp), (dhcp), (static) or (default).
Name resolution
OTP’s default lookup method on Unix is native, which spawns the port program
inet_gethost. That binary is not in the image, so /init writes
/etc/inetrc:
{lookup, [file, dns]}.
{host, {127,0,0,1}, ["localhost"]}.
{edns, 0}.
and points ERL_INETRC at it. Lookups then go through inet_res, OTP’s
resolver written in Erlang, which reads nameservers from /etc/resolv.conf.
/init writes that file from uniapp.dns. Keep both files: inet_db
re-reads resolv.conf periodically and a missing file clears the nameserver
list.
:inet.gethostbyname/1, :gen_tcp.connect(~c"host", ...), :httpc,
Req, Finch and friends all work through this path.
TLS
OpenSSL 3.5 is statically linked into beam.smp, so :crypto, :ssl and
:public_key are available without any files. For verifying servers, the
image ships Alpine’s CA bundle at /etc/ssl/cacert.pem:
:ssl.connect(~c"www.erlang.org", 443,
verify: :verify_peer,
cacertfile: ~c"/etc/ssl/cacert.pem",
versions: [:"tlsv1.3"],
server_name_indication: ~c"www.erlang.org")
For a TLS server, generate a certificate at boot (the sample app uses
:public_key.pkix_test_data/1 with digest: :sha256; SHA-1 signed test
certificates are rejected by modern clients) or ship a certificate and key in
priv/ of your release.
Reaching the guest from the host
With QEMU user networking the guest is not routable from the host; use port
forwards. The Makefile forwards host 14000, 14001 and 14443 to guest 4000
(TCP), 4001 (UDP) and 4443 (TCP). Add more in QEMU_BASE, or switch to a tap
device for a real bridged network.
Known gaps on Asterinas
- Binding to
0.0.0.0attaches the socket to the NIC only, so traffic to127.0.0.1does not reach a socket bound to the wildcard address. Bind explicitly to127.0.0.1for loopback-only servers. This comes from the local patch that makes wildcard binds work at all; see Asterinas patches. :inet.getifaddrs/0works on Asterinasmainbut returned{:error, :eaddrnotavail}on v0.18.1.- IPv6 is untested.