% cat fly.toml
app = "h2c"
[build]
image = "registry.fly.io/h2c:latest"
[[services]]
internal_port = 808
protocol = "tcp"
[[services.ports]]
port = "80"
% curl --http2 -6 http://h2c.fly.dev
Proto: HTTP/2.0
RemoteAddr: 136.144.55.141:36696
The IP 136.144.55.141
is certainly not mine, I’m guessing it’s a Fly host from Packet, located in Equinix SV15 in Santa Clara.
I think I misunderstood from the documents that lack of a handler for an externally exposed port just meant direct routing to the application, with no Layer 4 or above intermediary in between.
I stopped and thought about if this expectation is even realistic. First I thought it passes the smell test. Assuming IPs (v4 and v6) are dedicated to applications, they can be announced from Firecracker hosts hosting them and attract traffic from whatever edge a client ingresses from. But wait, in the docs it says TLS termination is done at the ingress edge. One can have multiple external ports with different set of handlers. So it’s not as straightforward as just speaking BGP from all hosts and anycast all the way up. Then I realized, hey I’m not paid to think about this, in fact I’m trying to pay for the service, so here I am…
Is it possible to terminate a TCP connection from the internet on the VM? If so, how? If not, do you intend to support this?
For the curious, this is the placeholder code running behind h2c.fly.dev.
package main
import (
"fmt"
"log"
"net/http"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
func main() {
var h http.HandlerFunc = func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("content-type", "text/plain")
w.WriteHeader(200)
fmt.Fprintln(w, "Proto:", req.Proto)
fmt.Fprintln(w, "RemoteAddr:", req.RemoteAddr)
}
log.Fatal(http.ListenAndServe(":8080", h2c.NewHandler(h, new(http2.Server))))
}