You "pass" a localhost check by sending the request to localhost (or 127.* or ::1). For example, you can make a web browser do this by navigating to http://localhost/ or http://[::1]/. The C# code snippet you posted for the server is checking the local IP address, so for a server that's the IP address the server received the connection request at, and from a client's perspective it's the IP address that the client is trying to connect to (the destination).
If you try sending such a request from any machine other than the one you're attempting to connect to, you'll route the request to your own machine, which is not what you want (but is the point of the loopback address). If you try crafting raw Ethernet packets that just happen to contain TCP/IP traffic, and set the IP destination to 127.0.0.1 but try to transmit the packet to another machine (via MAC address), one of these things will happen:
- You'll get an error from your network stack, because the packet was recognized to be IP traffic and is being transmitted wrong. Most network drivers probably won't do this, though, and if they do you can (in theory) edit that behavior out.
- Your packet will go out on the network, but be rejected by the first node it arrives at (probably a switch or router, unless you have a direct connection to the other machine) because, again, it is invalid; it's bound for the loopback network but comes from an external network. This might be what you're seeing in Wireshark.
- Your packet will be accepted by a router or switch, but passed to that router/switch's loopback network (after all, that's the destination IP address) rather than passing it on to any other host (it doesn't know where next to send the packet). This would be a security bug in the device and well worth reporting to the manufacturer if found.
- Your packet will go to the destination computer (if directly connected, or possibly if broadcast through a network hub), and be initially accepted by the network stack as a TCP
SYN packet. However, when the server tries to respond with
SYN/ACK, it will fail because it is trying to send an invalid packet (originating with localhost but bound for an outside host). This is still probably a security bug in the network driver / IP stack, because UDP packets don't require a handshake like that. Very much worth reporting.
- Your packet reaches the destination host and is accepted (as above), and you get a TCP
SYN/ACK from the server, inviting you to complete the handshake with a final
ACK and start transmitting data. You'd probably need a raw socket listener for this, because the OS network stack isn't going to recognize the incoming packet as part of a TCP handshake it was working on (though you could, theoretically, patch it to do so). This indicates a serious security bug in the server's network stack.
Note that in none of these cases, except the last one, is there any chance of the C# web server ever seeing the request come in. HTTP is transmitted over TCP, and TCP servers aren't even notified that somebody is connecting to them until the handshake completes. So, unless you've got a really serious bug in your network stack and are connected pretty directly, this is never going to happen.
Now, if you want to know how to reach a server listening only on loopback from outside the machine, the solution to that is to find some program on the same host as the target server that does listen to outside traffic, and will either relay requests to specified destinations (a proxy), or that can be used to create new web requests (this is a Server-Side Request Forgery (SSRF) attack, and one common way to create them is through an XML eXternal Entity (XXE) attack).