The worst one act play ever.
New User: Hello Magento Site, give me a catalog listing page
Varnish: Someone wants a page, do I have it cached? Yes! Since I
have it cached, I don't need to talk to Magento, I can just sent
the user this page.
[Varnish grabs the page]
Also, since there's no form key, I'll send back a newly generated
session ID! I'm so smart!
Uh oh, ESI includes. Better ask my ESI sub-routines to
handle those. Hey ESI, here's a page.
ESI: Hmmm, looks like this cached page has ESI includes on
it. I'll need to fetch those parts from Magento after all. I
don't have a frontend session ID to send, so I'll send along a
newly generated session ID. I'm so smart!
ESI: Hey Magento! Give me a form key. (Also, here's a newly
generated frontend session ID)
Magento: OK, here's a form key. Also, here's a cookie with the
session ID set. If you use this frontend session id again I'll
give you the same form key.
ESI: Hey Magento! Give me another form key (Also, here's a
newly generated frontend session ID)
Magento: Um, ok. That's a different frontend session ID, but
here's a new form key. Also, here's a cookie with the session ID
set.
etc...
ESI: OK Varnish, all ESI includes replaced
Varnish: Great work ESI, now I'll send the page back, and I'll
send it back with that first frontend session ID cookie so that
future requests will use the same thing.
So, varnish correctly generates the session id. The underlying problem here is, for the first request only, varnish will not use that generated session ID cookie for the ESI request. The ESI requests seem to look at the original request. The creates problems if that first page has CSRF form key protections.
I'll have a look at the VCL.
PS. Real funny, I just wrote a Bob & Alice dialog about the locking of the configuration cache.