How to Bind and Send from Google Cloud Forwarding Rule IP Address?
<p>I've followed the instructions for <a href="https://cloud.google.com/compute/docs/protocol-forwarding/" rel="noreferrer">Using Protocol Forwarding</a> on the Google Cloud Platform. So I now have something like this:</p>

<pre><code>$ gcloud compute forwarding-rules list
NAME    REGION    IP_ADDRESS      IP_PROTOCOL  TARGET
x-fr-1  us-west1  104.198.?.??    TCP          us-west1-a/targetInstances/x-target-instance
x-fr-2  us-west1  104.198.?.??    TCP          us-west1-a/targetInstances/x-target-instance
x-fr-3  us-west1  104.198.??.???  TCP          us-west1-a/targetInstances/x-target-instance
x-fr-4  us-west1  104.198.??.???  TCP          us-west1-a/targetInstances/x-target-instance
x-fr-5  us-west1  104.198.?.???   TCP          us-west1-a/targetInstances/x-target-instance
</code></pre>

<p>(Note: Names have been changed and question-marks have been substituted. I'm not sure it matters to keep these private but better safe than sorry.)</p>

<p>My instance "x" is in the "x-target-instance" and has five forwarding rules "x-fr-1" through "x-fr-5". I'm running nginx on "x" and I can access it from any of its 6 external IP addresses (1 for the instance + 5 forwarding rules). So far, so good.</p>

<p>I am interested now in binding a server to these external IP addresses. To explore, I tried using Python:</p>

<pre><code>import socket
import time

def serve(ip_address, port=80):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((ip_address, port))
    try:
        sock.listen(5)
        while True:
            con, _ = sock.accept()
            print con.getpeername(), con.getsockname()
            con.send(time.ctime())
            con.close()
    finally:
        sock.close()
</code></pre>

<p>Now I can bind "0.0.0.0" and I get some interesting results:</p>

<pre><code>&gt;&gt;&gt; serve("0.0.0.0")
('173.228.???.??', 57288) ('10.240.?.?', 80)
('173.228.???.??', 57286) ('104.198.?.??', 80)
</code></pre>

<p>When I communicate with the server on its external IP address, the "getsockname" method returns the instance's internal IP address. But when I communicate with the server on an external IP address as used by a forwarding rule, then the "getsockname" methods returns the external IP address.</p>

<p>Ok, now I bind the instance's internal IP address:</p>

<pre><code>&gt;&gt;&gt; serve("10.240.?.?")
('173.228.???.??', 57295) ('10.240.?.?', 80)
</code></pre>

<p>Again I can communicate with the server on its external IP address, and the "getsockname" method returns the instance's internal IP address. That seems a bit odd.</p>

<p>Also, if I try to bind the instance's external IP address:</p>

<pre><code>&gt;&gt;&gt; serve("104.198.?.??")
error: [Errno 99] Cannot assign requested address
</code></pre>

<p>Then I get an error.</p>

<p>But, if I try to bind the external IP addresses used by the forwarding rules and then make a request:</p>

<pre><code>&gt;&gt;&gt; serve("104.198.??.???")
('173.228.???.??', 57313) ('104.198.??.???', 80)
</code></pre>

<p>It works.</p>

<p>Finally I look at "ifconfig":</p>

<pre><code>ens4      Link encap:Ethernet  HWaddr 42:01:0a:??:??:??  
          inet addr:10.240.?.?  Bcast:10.240.?.?  Mask:255.255.255.255
          inet6 addr: fe80::4001:???:????:2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
          RX packets:37554 errors:0 dropped:0 overruns:0 frame:0
          TX packets:32286 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:41201244 (41.2 MB)  TX bytes:3339072 (3.3 MB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:9403 errors:0 dropped:0 overruns:0 frame:0
          TX packets:9403 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:3155046 (3.1 MB)  TX bytes:3155046 (3.1 MB)
</code></pre>

<p>And I see only two interfaces. Clearly, the abilities of Google Cloud Platform Networking has exceeded what I can remember from my Computer Networking class in college. To summarize my observations:</p>

<ol>
<li>If I want to bind on the instance's external IP address, then I bind its internal IP address.</li>
<li>A process bound to the instance's internal IP address can not differentiate the destination IP between the instance's internal or external IP addresses.</li>
<li>The single networking adapter, "ens4", is receiving packets bound for any of the instance's 6 external IP address.</li>
</ol>

<p>And here's my questions:</p>

<ol>
<li>Why can I not bind the instance's external IP address?</li>
<li>How is it that I can bind the external IP addresses used by forwarding rules when I have no associated network adapters?</li>
<li>If I want to restrict SSH access to the instance's external IP address, should I configure SSH to bind the internal IP address?</li>
<li>If I setup an HTTP proxy on one of the external IP addresses used by a forwarding rule, what will be the source IP of the proxied request?</li>
<li>Lastly, and this may be a bug, why is the forwarding rules list empty in the web interface at <a href="https://console.cloud.google.com/networking/loadbalancing/advanced/forwardingRules/list?project=xxx" rel="noreferrer">https://console.cloud.google.com/networking/loadbalancing/advanced/forwardingRules/list?project=xxx</a> when I can see them with "gcloud compute forwarding-rules list"?</li>
</ol>