why MASQUERADE SNAT can block localhost connection?

I don't know if it is a bug or an intentional fallback behavior, but from I what can see here, it has neither anything to do with the wlan0 local route you mentioned, or all the default gateway blah blah (no offense but it almost makes no sense to me) stated in the other/"correct" answer.

Normally how MASQUERADE works is, it picks the address that is configured on the outbound interface (which is determined by routing, hence POSTROUTING) for the source NAT that it performs. (If multiple addresses are assigned on the interface, it will probably pick the first one or the one that is set as the preferred source address in the corresponding route; I'm not that familiar with it and that is out-of-scope here anyway). It has nothing to do with the nexthop / gateway address of the default route. (That's not how source NAT works anyway.)

However, when it comes to the interface lo, things seems to become a bit tricky. More precisely, it does not seem to have something to do with the interface itself (apart from the fact that it will be the outbound interface because the destination is a local address), but rather the fact that, addresses in the 127.0.0.0/8 block is not of scope global. While I have no idea what is happening behind the scene, it seems that the traffic cannot "show up" if the host has no scope global IP address configured but attempt to MASQUERADE.

What I can see here is, even if you just configure an address that is valid for scope global (e.g. 192.168.0.10/32) on any interface (including lo), you'll see it works again. (The local route you mentioned will be added automatically. But I'm not seeing that adding only the route works here.)

For what it's worth, addresses and interfaces are not heavily bound together in Linux (not in a straight-forward way like, it will reply to traffics only if their destination address matches with the configured address on the inbound interface, even when IP forwarding is not of concern). So it might has something to do with that: in case MASQUERADE cannot pick a scope global address from what are configured on the outbound interface, it just pick one from any (I doubt that the precedence has something to do with default route though), if still no, it just refuse to work in some way.

In case you really need a rule that enables MASQUERADE on all interfaces but lo, you can have:

iptables -t nat -A POSTROUTING ! -o lo -j MASQUERADE

This is an educated guess. The MASQUERADE option replaces the source IP address in IP packets with the address it decides to use. I think in this case, it replaces the source address with the interface address where default gateway is reachable.

So, if your default gateway is 192.168.0.1, the source address of the packet is replaced with 192.168.0.1. The destination is 127.0.0.1, and this doesn't work properly.

You should limit MASQUERADE to only packets where outgoing interface is the one towards default gateway.

You can do it with the following command:

iptables -t nat -A POSTROUTING -o <if> -j MASQUERADE