Search code examples
c#httpubuntugoogle-cloud-platformport

How to open Google VM to external HTTP connection?


I'm trying to make a simple C# HTTP Listener that listens for external connections. I installed dotnet on the VM Instance(uses Ubuntu 22.04 by the way), and uploaded my source files for the HTTP Listener. This is the code:
Program.cs:

using System;
...
public class Program
{
    public const string ADDRESS = "http://VM_EXTERNAL_IP";
    public const int PORT = 80;
    public static Server server;
    static void Main(string[] args)
    {
        server = new Server(ADDRESS, PORT);
    }
}

Server.cs:

public class Server
{
    public string address;
    public int port;
    public Server(string address, int port)
    {
        HttpListener httpserver = new HttpListener();
        httpserver.Prefixes.Add(address + ":" + port + "/");

        httpserver.Start();

        Console.WriteLine("Listening on " + address + ":" + port + "/");
        while (httpserver.IsListening)
        {
            HandleHTTPConnections(httpserver);
        }
    }
}

I don't think the request-response handler code is relevant, because this part: httpserver.Prefixes.Add(address + ":" + port + "/");, gives me errors:

Unhandled exception. System.Net.HttpListenerException (99): Cannot assign requested address
   at System.Net.HttpEndPointManager.GetEPListener(String host, Int32 port, HttpListener listener, Boolean secure)
   at System.Net.HttpEndPointManager.AddPrefixInternal(String p, HttpListener listener)
   at System.Net.HttpEndPointManager.AddListener(HttpListener listener)

Now, I tried to set the address to a lot of values and here is the outcomes of each try:

  1. VM External IP - `ADDRESS = "http://34.118.16.122"`: The error from above
  2. VM Internal IP - `ADDRESS = "http://10.186.0.2"`: The same error from above
  3. Generic - `ADDRESS = "http://+"`: Another error that states that ADDRESS is already in use by other process
  4. `ADDRESS = "http://localhost"`: It doesn't give me any errors but that doesn't achieve the goal which is to connect from outside.

Now, I want to mention that when I rand this code on my Windows PC and did the port forwarding in my personal router on 80, I managed to connect from outside my local network by using the global IP of my router, instead of the `192.168.X.X` one. Because of this success on my PC I believed that maybe I need to do the equivalent of port forwarding but on the Google Cloud's VM Instance, so I asked Google Cloud's Assistant AI and told me that I need to redirect the port `80` to `22` using `ssh -L 80:localhost:22 user@EXTERNAL_IP_ADDRESS` command. I tried to run this command in the Ubuntu shell however I got "Permission denied" error message even thou I was logged as superuser. However as far as I understand the SSH is a different protocol than HTTP and updating SSH port wouldn't change anything regarding HTTP.

The next thing I tried is setting a new firewall rule that allows any HTTP connection on port 80 on any internal IP address, however this didn't change anything.

So after reading what I tried to explain here, maybe you can tell me what to try next?


Solution

  • Use the address http://*, and not the external IP address which is not accessible from the VM's network stack.

    The address * means listen on all network adapters for connection requests.

    httpserver.Prefixes.Add("http://*:" + port.ToString() + "/");