Yet, when I attempt to attach using a Public IP (either the DNS AWS gave me or an Elastic IP) I get some strange behavior:
Is there some DNS hoodoo I need to attend to? That's what it seems like. I am not connecting to the 'Listener'.
Let me explain how read only routing works and then I think you'll understand since you've done a fairly good job investigating on your own.
When you setup read only routing you have an endpoint url and a routing list. The routing list is for the most part, ordinary, it lists who to go to and when, depending on various situations. The endpoint url, however, is the real key here. This is setup to point to a TDS endpoint (which is the protocol SQL Server uses to communicate to clients and other servers).
The TDS specification defines this behavior, so when read only routing is evaluated and the server decides that this connection is indeed good to be read only routing to a specific replica, it fills in the bits in the TDS packet to send back to the client saying that there will be an environment change, this is read only routing, and it's going to now go to the endpoint url that was previously configured.
Here's where you run into a problem as you have a private address and a public address. The routing url is most likely configured with the private address, which is what is passed directly back to the client driver. Let's make up some IPv4 addresses (works with IPv6 too), let's say the internal AWS address is 192.168.1.20 and the public address is 20.153.200.5 - great. If the routing url was configured with 192.168.1.20, then this will be passed back to the client driver, the client driver will then disconnect from the current connection to the primary and create a new connection with the exact url it was given, in this case 192.168.1.20. This works when you're inside your private area as this can be resolved quite easily. However, when you're outside AWS, say at your home without VPN or other items, the client driver will still get the same value and still try to connect to the same address, 192.168.1.20 - it's at this point, that's not going to resolve anywhere helpful and you will get the error you've been receiving.
There isn't a whole lot you can do... you can make your own host entries, aliases, etc., but if the internal servers can resolve the public address and you're going to use it from the outside more than internally, I'd make the routing url the public address.