<feed xmlns='http://www.w3.org/2005/Atom'>
<title>hetzner-infra/vpn/docker-compose.yml, branch master</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/'/>
<entry>
<title>Fix VPN cert chain: split multi-cert PEM for strongSwan</title>
<updated>2026-07-01T15:28:31+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T15:28:31+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=c463eddaab816b6ffe032f37f4228e4b22a1425d'/>
<id>c463eddaab816b6ffe032f37f4228e4b22a1425d</id>
<content type='text'>
Caddy's cert chain contains 4 certs:
  1. leaf (signed by YE1)
  2. YE1 (signed by Root YE)
  3. Root YE (cross-signed by ISRG Root X2)
  4. ISRG Root X2 (cross-signed by ISRG Root X1)

iOS/Android trust ISRG Root X1 but not Root YE directly.
The full cross-signed chain must be sent in IKE_AUTH.

strongSwan only reads the first cert from a multi-cert PEM file,
so entrypoint.sh now splits server-chain.crt into individual files
in x509ca/ before starting charon.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Caddy's cert chain contains 4 certs:
  1. leaf (signed by YE1)
  2. YE1 (signed by Root YE)
  3. Root YE (cross-signed by ISRG Root X2)
  4. ISRG Root X2 (cross-signed by ISRG Root X1)

iOS/Android trust ISRG Root X1 but not Root YE directly.
The full cross-signed chain must be sent in IKE_AUTH.

strongSwan only reads the first cert from a multi-cert PEM file,
so entrypoint.sh now splits server-chain.crt into individual files
in x509ca/ before starting charon.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Restore intermediate cert + reduce IKE fragment size to 512 bytes</title>
<updated>2026-07-01T15:21:40+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T15:21:40+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=86bc044356ae37aa24ff352858d71641c00740fc'/>
<id>86bc044356ae37aa24ff352858d71641c00740fc</id>
<content type='text'>
iOS/Android VPN stacks don't follow AIA to download intermediate certs,
so YE1 must be sent by the server for cert chain validation.

The original 1236-byte IKE fragment was being dropped mid-path.
Setting fragment_size=512 splits the 1776-byte IKE_AUTH into ~4
fragments of ≤560 bytes each, which should traverse any NAT/router.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
iOS/Android VPN stacks don't follow AIA to download intermediate certs,
so YE1 must be sent by the server for cert chain validation.

The original 1236-byte IKE fragment was being dropped mid-path.
Setting fragment_size=512 splits the 1776-byte IKE_AUTH into ~4
fragments of ≤560 bytes each, which should traverse any NAT/router.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove intermediate CA cert to fix IKE fragmentation</title>
<updated>2026-07-01T10:39:22+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T10:39:22+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=a86a5b9d1f68f292e33dfc0ed04b87c5ca785382'/>
<id>a86a5b9d1f68f292e33dfc0ed04b87c5ca785382</id>
<content type='text'>
YE1 intermediate cert was inflating IKE_AUTH response to 1776 bytes,
causing it to be split into 2 IKE fragments that iOS/Android clients
could not reassemble. Both iOS and Android 12 (Beam Pro) have
Let's Encrypt trust chain in their system store, so the intermediate
cert is not needed.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
YE1 intermediate cert was inflating IKE_AUTH response to 1776 bytes,
causing it to be split into 2 IKE fragments that iOS/Android clients
could not reassemble. Both iOS and Android 12 (Beam Pro) have
Let's Encrypt trust chain in their system store, so the intermediate
cert is not needed.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Revert VPN file logging (caused container crash)</title>
<updated>2026-07-01T10:10:52+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T10:10:52+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=ff3b39b124cf73599b9b075ae1c7ec63f9d78f4c'/>
<id>ff3b39b124cf73599b9b075ae1c7ec63f9d78f4c</id>
<content type='text'>
Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add file logging to VPN container for diagnostics</title>
<updated>2026-07-01T08:35:43+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T08:35:43+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=06da418ded2b88e8d83fd02cb0f9bb7bd3c826bc'/>
<id>06da418ded2b88e8d83fd02cb0f9bb7bd3c826bc</id>
<content type='text'>
Logs to /home/yyamashita/vpn-logs/charon.log (readable without root)
to diagnose iPhone IKEv2 connection failures.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Logs to /home/yyamashita/vpn-logs/charon.log (readable without root)
to diagnose iPhone IKEv2 connection failures.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Restore intermediate CA cert, disable IKE fragmentation</title>
<updated>2026-07-01T03:30:02+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T03:30:02+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=75686581d208ba4b4263420db169f56083dda52b'/>
<id>75686581d208ba4b4263420db169f56083dda52b</id>
<content type='text'>
Android (XREAL Beam Pro) fails to reassemble IKE fragments even though
FRAG_SUP is negotiated. IP-level fragmentation (handled by the OS kernel)
works better. Removing the intermediate cert broke macOS/iOS.

This config:
- Sends leaf cert + YE1 intermediate (so any client can verify the chain)
- fragment_size=0 disables IKE fragmentation; the 1776-byte IKE_AUTH
  response is sent as one large UDP packet (OS handles IP fragmentation)

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Android (XREAL Beam Pro) fails to reassemble IKE fragments even though
FRAG_SUP is negotiated. IP-level fragmentation (handled by the OS kernel)
works better. Removing the intermediate cert broke macOS/iOS.

This config:
- Sends leaf cert + YE1 intermediate (so any client can verify the chain)
- fragment_size=0 disables IKE fragmentation; the 1776-byte IKE_AUTH
  response is sent as one large UDP packet (OS handles IP fragmentation)

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Remove intermediate CA cert mount to fix Android IKEv2 fragmentation</title>
<updated>2026-07-01T01:29:36+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T01:29:36+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=acff0eebed7cd89a5b50db2366cd055d6aed67de'/>
<id>acff0eebed7cd89a5b50db2366cd055d6aed67de</id>
<content type='text'>
Android (XREAL Beam Pro) advertises FRAG_SUP but fails to reassemble
IKE fragments. The IKE_AUTH response was 1776 bytes (leaf + YE1 intermediate)
requiring fragmentation into 2 packets. Without x509ca mount, only the leaf
cert is sent (~886 bytes total), fitting in a single packet without fragmentation.
Android fetches the intermediate CA (YE1) via AIA extension before tunnel setup.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Android (XREAL Beam Pro) advertises FRAG_SUP but fails to reassemble
IKE fragments. The IKE_AUTH response was 1776 bytes (leaf + YE1 intermediate)
requiring fragmentation into 2 packets. Without x509ca mount, only the leaf
cert is sent (~886 bytes total), fitting in a single packet without fragmentation.
Android fetches the intermediate CA (YE1) via AIA extension before tunnel setup.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix VPN: send certificate always, split cert chain, fix entrypoint</title>
<updated>2026-07-01T01:16:13+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-07-01T01:16:13+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=11b6518b75e06dcd716bf04e133ef1a67c591cae'/>
<id>11b6518b75e06dcd716bf04e133ef1a67c591cae</id>
<content type='text'>
- swanctl.conf.tpl: send_cert = always (fix Android cert verification failure)
- docker-compose.yml: mount intermediate CAs to /etc/swanctl/x509ca/
- install.sh: split server.crt into leaf + chain for proper chain distribution
- entrypoint.sh: run charon directly for Docker log visibility,
  fix sysctl error handling, fix charon binary path
- strongswan.conf: increase IKE log level to 4 for debugging

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- swanctl.conf.tpl: send_cert = always (fix Android cert verification failure)
- docker-compose.yml: mount intermediate CAs to /etc/swanctl/x509ca/
- install.sh: split server.crt into leaf + chain for proper chain distribution
- entrypoint.sh: run charon directly for Docker log visibility,
  fix sysctl error handling, fix charon binary path
- strongswan.conf: increase IKE log level to 4 for debugging

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Add strongSwan IKEv2 VPN service</title>
<updated>2026-06-30T13:29:07+00:00</updated>
<author>
<name>yyamashita</name>
<email>yyamashita@hetzner.yyamashita.com</email>
</author>
<published>2026-06-30T13:29:07+00:00</published>
<link rel='alternate' type='text/html' href='http://git.yyamashita.com/hetzner-infra/commit/?id=58f7917662ff92a3712289acccff8310c8f1baff'/>
<id>58f7917662ff92a3712289acccff8310c8f1baff</id>
<content type='text'>
- vpn/: Dockerfile, docker-compose.yml, swanctl.conf.tpl, entrypoint.sh
- install.sh: Caddy 証明書流用 + コンテナ起動
- renew-cert.sh: 証明書更新 + swanctl ホットリロード
- caddy/Caddyfile: vpn.yyamashita.com 追加（Let's Encrypt 証明書取得用）
- post-receive: vpn/deploy.sh を追加
- setup-route53.py: WEB_SUBDOMAINS に vpn を追加

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
- vpn/: Dockerfile, docker-compose.yml, swanctl.conf.tpl, entrypoint.sh
- install.sh: Caddy 証明書流用 + コンテナ起動
- renew-cert.sh: 証明書更新 + swanctl ホットリロード
- caddy/Caddyfile: vpn.yyamashita.com 追加（Let's Encrypt 証明書取得用）
- post-receive: vpn/deploy.sh を追加
- setup-route53.py: WEB_SUBDOMAINS に vpn を追加

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
