Freechess shipped a binary called “timeseal” that did the calculations for you and encrypted the communications. It was not foolproof—-not by a long shot, but it also didn’t completely suck.
Well it's a long time since I played there. But it had custom chess clients, which I assume just recorded how much time your move actually took and sent that with the move.
Yes, it's easy to cheat with this, but it's very easy to cheat with chess anyway.
This makes the most sense. Start a timer when the UI actually hands control to the player whose move it is, stop the timer when they've completed their move, and simply subtract that from their remaining time. The interval gets sent to the server and relayed to the other player to update their opponent's clock accurately.