I tried the wildcard Craig, that works for me too, sweet! I've also learned a bit more in the meanwhile. I've had a chance to play with multiple trunks for backup IP signalling with verbose logging on 3CX and tcpdump on Debian. I think I can establish that the first trunk used is the first that matches the DID and then the IP, from bottom to top. I should first say my setup uses IP auth not user/pass. I tested this with the following trunks in this order:
Name Host DID
IN1 z.z mydid
IN2 x.y mydid
OUT x.y 1111
The above trunk setup, incoming calls come in on IP x.y and match mydid, so IN2 is used. If I change the DID field the OUT trunk to mydid, the OUT rule is used for incoming calls. So the bogus '1111' is useful for 3CX to bypass this trunk since no DID match and go up the trunks until the first match. I inverted the Host section for IN1 and IN2 and now see trunk IN1 being utilized on the inbound call. I'd love to force the provider to send signalling on another IP but I'm fairly confident this works.
So now it's clear that 3CX was using my OUT rule before because it was the first trunk that matched my DID and Host both. I had the Allow Inbound Calls Option unchecked on that OUT rule before and while it's obvious why I didn't get an inbound call because of that, I find the error 3CX gave is a bit bizarre.