The first method I'd considered was to simply block all IP ranges that were registered to one of the countries in question. You can easily find several sites that offer the complete lists of IP blocks registered to other countries in an Internet search. Problem is, these blocks are hundreds (or in the case of China, thousands) of subnets long. Adding them into your firewall rules would practically gag your server, especially in the case of low-latency applications such as games and VoIP.
After doing some additional digging, a solution presented itself that allows a much lower processing overhead, but still allows you to completely block countries. Don't do the blocking directly in your ipchains or pf configuration, do it in your hosts.deny file.
The way you do this is to not filter by IP address, but rather by Top Level Domain extension. In other words, use the Internet-abbreviated country code. Here's an example of a hosts.deny file that's blocking France, China, Russia, Ukraine, and several others:
This adds a couple dozen firewall rules, and the time it takes to do a reverse DNS lookup into your server access time, instead of going through thousands of IP subnet firewall rules. And since iptables and pf preserve open connection states outside of firewall rules, these firewall rules are only examined when the connection is initiated, resulting only in an additional 50-100ms latency response time on the initial request.
Is it 100% bulletproof? Nope. But it's brought the number of hack attempts down for my servers exponentially. Most importantly, it means less time fighting off hackers, and more time working on that bottle of Balvenie Doublewood 12-year that's been sitting on my shelf for a while.