Sorry to say, my Accept.js module won't help here. eProcessingNetwork emulates Authorize.Net's AIM interface, and my module talks to the JSON API with Accept.js tokenization, which ePN doesn't emulate as far as I know. So this stays with the AIM module, and for what it's worth, here's how the symptoms read to me.
Error 28 is curl's own timeout rather than a gateway rejection. The AIM module allows 15 seconds for the reply (CURLOPT_TIMEOUT in includes/modules/payment/authorizenet_aim.php), and "0 bytes received" says the connection and the POST succeeded, the gateway took the transaction, and the answer just didn't come back in that window. That fits the charge appearing at the gateway with no order on the Zen Cart side.
curltester probably isn't telling you much in this case. It connects to secure2.authorize.net and api.authorize.net rather than the ePN emulation address the module has been pointed at, and it doesn't send a transaction, so a timeout on the reply wouldn't show up there.
If it were mine, I'd time the real endpoint from the server. The Debug Log's masked request dump has a "url" line with the address the module posts to, and a bogus login gets a quick "login invalid" reply without touching a card:
curl -sS -o /dev/null -w 'http %{http_code} first byte %{time_starttransfer}s total %{time_total}s\n' --max-time 60 -d 'x_login=test&x_tran_key=test' https://www.eprocessingnetwork.com/cgi-bin/an/order.pl
If the first byte takes longer than 15 seconds, the gateway itself has slowed down, and ePN would be the ones to ask. If it answers quickly with --http1.1 added but stalls without it, a newer curl on the host has started negotiating HTTP/2 and ePN's front end isn't handling it. Either one would explain "stopped last week with nothing changed on the store": a cPanel/EasyApache rebuild updates curl, and gateways change their front ends without saying so.
If it does come down to the timeout, the change is small, in the same file that already carries the ePN address:
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Expect:']);
The longer timeout covers a slow gateway, the HTTP/1.1 pin takes HTTP/2 out of the picture, and the empty Expect header avoids the 100-continue stall some gateways have with curl posts. One thing worth keeping in mind while testing: each attempt that times out is still a real charge at the gateway, and a retry creates another. Authorize.Net's duplicate window is a feature of their system, so the ePN emulator may not support it.
Hope some of that helps.