[HN Gopher] How to make "localhost" slightly less local
       ___________________________________________________________________
        
       How to make "localhost" slightly less local
        
       Author : brycewray
       Score  : 39 points
       Date   : 2022-04-02 16:53 UTC (6 hours ago)
        
 (HTM) web link (www.brycewray.com)
 (TXT) w3m dump (www.brycewray.com)
        
       | aussieguy1234 wrote:
       | You can follow these steps and learn about network interfaces and
       | IP addresses or you can use my app (https://expose.sh) and get a
       | public URL for your service in a single command.
       | 
       | Note: This won't only make your localhost service slightly less
       | local, but also publicly accessible.
       | 
       | Example: `expose 80`
        
       | jeroenhd wrote:
       | ...and then you'll find out that all kinds of fancy JS features
       | don't work any more because of something called a "secure
       | origin"! Soon after you end up in a rabbit hole of acronyms like
       | CORS, XHR, CSP, TLS, HSTS, (m)DNS, WSS and HTTPS, and soon enough
       | you'll be copy/pasting a hundred of lines of configuration just
       | to make your website work like it did on localhost.
       | 
       | I enjoy the ease of use that the special privileges localhost was
       | given in browsers, but I'm 100% sure it's a pitfall for starting
       | developers. It's still confusing to me that someone capable of
       | developing a website needs an explainer on how basic computer
       | networking works, but I guess other people learn about computers
       | top-down rather than bottom-up. I have no idea what all of these
       | servers are (most of them seem Javascript based?) but I'd expect
       | someone knowing how to deal with a piece of complex server
       | software like that to at least know where to find their machine's
       | IP address!
        
       | devmor wrote:
       | Or you can just bridge the connection and use mDNS?
        
       | tedunangst wrote:
       | Back in the day, you used to be able to connect to services bound
       | to 127.1 on host A from host B by deleting 127.1 on host B, then
       | adding a manual route to host A's public IP. Host B stack sees
       | packet for 127.1, says not me, routes it to host A, host A gets
       | packet, looks at its IPs, sees 127.1, says oh this must be for
       | me. Most systems are probably better about configuring host A to
       | not let this happen now.
        
       | svnpenn wrote:
       | Is it possible to access the local site from another network?
       | Like run a local server, that I can access from my phone outside
       | of the house? I looked into this before, but I could never find a
       | simple solution.
        
         | mhitza wrote:
         | Use something like ngrok (or manual ssh tunnels), just be sure
         | to have some authentication in place.
        
         | skinnymuch wrote:
         | Tailscale as others have said. ZeroTier if not Tailscale. Both
         | are top notch
        
         | johnny35 wrote:
         | Look into Tailscale. Ridiculously easy to set up and free for
         | your use case.
        
           | newaccount74 wrote:
           | +1 on Tailscale. It took me time to accept using a closed
           | source free product, but it's just such a nice product --
           | they focussed on the essentials and it works really well.
        
             | skinnymuch wrote:
             | It seems like they have gone past essentials now. Like
             | being able to use any connected device as an endpoint? I
             | haven't used Tailscale yet past as a mesh network but
             | regardless. It is so well done.
        
         | jeroenhd wrote:
         | With IPv6: yes, if you open the port in your firewall.
         | 
         | With IPv4 you can do it with a port forward, but the IP listed
         | isn't the same as the IP you'll actually receive the connection
         | on. You can get your external IP relatively easily with `curl
         | ifconfig.co`.
         | 
         | If firewalls or port forwards aren't available to you, pick any
         | of the popular port forwarding methods (here's a list:
         | https://github.com/anderspitman/awesome-tunneling). I'm a big
         | fan of just SSH-ing into an internet connected machine myself
         | (`ssh -R 0.0.0.0:3000:127.0.0.1:3000 server.on.the.inter.net`
         | will expose localhost:3000 on server.on.the.inter.net:3000 and
         | encrypt the traffic between you and the server as an added
         | bonus!) but there are plenty of paid and sketchy alternatives
         | if you don't have a server to SSH into.
        
           | svnpenn wrote:
           | > If firewalls or port forwards aren't available to you
           | 
           | I don't know if they are or not. I am just a regular person
           | with a home computer. I know how to set up a run a basic
           | localhost server, but I don't really know about the other
           | stuff you're talking about.
        
       | mhitza wrote:
       | Not sure how mDNS service (Bonjour I think) is setup on macOS,
       | but you should be able to reach it by some domain name as well
       | (hostname.local format), once you expose your service on the
       | public IP address.
       | 
       | On Linux I have my VMs run avahi (the Linux mDNS service), and I
       | access my VMs using vmname.local instead of using hardcoded IP
       | addresses.
        
         | zdragnar wrote:
         | Android doesn't support mDNS at the OS level, so it is possible
         | to bake it into an app, but i.e. chrome won't connect. It is a
         | long standing issue that I don't think Google cares to
         | prioritize:
         | 
         | https://issuetracker.google.com/issues/140786115?pli=1
         | 
         | I would have sworn I saw that the latest pixel / android
         | versions could, but now I'm not finding one way or the other.
         | Given the issue above is still open, I am assuming not.
        
         | avip wrote:
         | I've always had issues using mDNS on a mixed os network. I
         | assume both bonjour and avahi and whatever windows uses comply
         | with some standard. But in (my) reality, it doesn't work.
        
       | maliker wrote:
       | I just use ngrok.com. Makes specific localhost ports accessible
       | regardless of network.
        
         | pricci wrote:
         | I prefer Cloudflare Tunnels.
         | 
         | Just install cloudflared.
        
         | [deleted]
        
         | janjones wrote:
         | Localtunnel[1] is also great, you don't even have to sign up.
         | 
         | [1] https://theboroer.github.io/localtunnel-www/
        
         | danielvaughn wrote:
         | I love ngrok outside of two pain points - (1) the urls are kind
         | of difficult to type into a phone, and (2) the latency can be
         | pretty terrible at times.
        
           | stuartd wrote:
           | The basic paid plan is pretty cheap and lets you use
           | your_subdomain_name.ngrok.com as the address.
        
           | paskozdilar wrote:
           | In my opinion, (2) is a feature, not a bug. You never know
           | what kind of connection your users have. Ngrok forces you to
           | consider the "bad connection" factor early on in development,
           | which can avoid many pitfalls that occur when network
           | software assumes that latency is zero and bandwidth is
           | unlimited.
        
             | skinnymuch wrote:
             | It's not a feature imo when there are other ways to force a
             | "bad connection". However with ngrok if latency is bad. You
             | can't ever change fhat.
        
               | paskozdilar wrote:
               | That's a fair point.
               | 
               | I suppose latency is important if you use ngrok for
               | something other than development. I use ngrok exclusively
               | for development, so that's where my comment comes from.
        
           | skinnymuch wrote:
           | I have switched over to using Tailscale. But that only works
           | if the devices are mine before the friction of someone else's
           | device being set up happens
        
       | pdpi wrote:
       | Your computer has multiple network interfaces, and it has routing
       | tables that tell it which interface to use for each IP it tries
       | to talk to. E.g. your home router basically has one interface
       | talking to the outside world and another talking to your local
       | network, and its whole job is patching together connections
       | through each of those interfaces.
       | 
       | Your personal computer will have ethernet and/or wifi, and those
       | are entirely separate network interfaces, but it will also have a
       | loopback interface (which is a dummy software-only interface that
       | just connects back to your computer). The "localhost" hostname
       | points at 127.0.0.1, and that IP is bound to the loopback
       | interface, so all connections through localhost won't even hit
       | the network, they'll just be looped back in (hence the name).
       | 
       | What all those -H/--host/--bind options do is tell your service
       | which of those network interfaces to bind to. Instead of
       | specifying an IP (and, therefore, an interface) to bind on, you
       | can use 0.0.0.0 as a catch-all "meta-IP" that will tell your
       | service to listen on all interfaces.
       | 
       | My personal preference (though it does require a bit more setup
       | ahead of time) is to keep all these (HTTP) services listening on
       | localhost, and then configure one single NGINX instance that
       | binds on the external interface and proxies each individual
       | service.
        
         | 1vuio0pswjnm7 wrote:
         | "The "localhost" hostname points at 127.0.0.1, but it will also
         | have a loopback interface (which is a dummy software-only
         | interface that just connects back to your computer)."
         | 
         | AFAIK, 127.0.0.1 localhost as a HOSTS file entry is merely a
         | convention. For example, the name "localhost" can point to any
         | address in the 127.x.x.x address space or any address in
         | general. Similarly, a loopback interface can be assigned any
         | 127.x.x.x address. The convention is to assign 127.0.0.1.
         | 
         | One of the nice things about NetBSD (IMO) is that when
         | compiling one's own system, a loopback is not necessarily
         | automatically created. It may be left up to the user to create
         | one and assign it with an address. This can teach the user what
         | software depends on the presence of a loopback interface that
         | is assigned "127.0.0.1".
        
           | pdpi wrote:
           | Yeah, and you can also have multiple loopback interfaces in
           | the 127.0.0.0/8 range if you want, no reason why you can only
           | have one. That said, enough stuff out there assumes localhost
           | = 127.0.0.1 = loopback interface that I wouldn't want to make
           | my life complicated by breaking the convention.
           | 
           | Also, that comment was already a bit muc, and I opted to
           | simplify a bit.
        
       | brycewray wrote:
       | I hope you'll find this helpful whenever you're web-dev'ing and
       | just can't remember that string of commands/flags/etc. for seeing
       | "localhost" from your other devices.
       | 
       | EDIT: post is now available also on dev.to[0].
       | 
       | [0]: https://dev.to/brycewray/let-all-your-devices-see-your-
       | site-...
        
       | [deleted]
        
       | mac-chaffee wrote:
       | I lost a lot of the blind faith I had in people who make http
       | servers when I realized some network configurations just can't be
       | expressed.
       | 
       | Like next.js's "Production Server"[1] uses Node's builtin server,
       | which doesn't natively let you listen on more than one IP. And
       | because next.js hardcodes 0.0.0.0, it doesn't also listen on the
       | IPv6 equivalent if available, which breaks some clients when
       | using "localhost" as the hostname (BusyBox wget as a notable
       | example I found).
       | 
       | [1]: https://nextjs.org/docs/api-reference/cli#production
        
         | fuzzy2 wrote:
         | But then Busybox wget is simply broken, sorry. It's still
         | entirely normal for a hostname to resolve to both IPv4 and IPv6
         | addresses, yet have some services not listening on both. Good
         | TCP clients implement a fallback mechanism that could be so
         | fast the user doesn't even notice.
        
           | Dylan16807 wrote:
           | That fallback is a workaround. Requiring it is simply broken.
        
           | mac-chaffee wrote:
           | If BusyBox did implement that kind of fallback, they'd need
           | to set a default timeout. So the whole thing would still be
           | broken because every other request would be delayed by the
           | timeout.
        
           | jeroenhd wrote:
           | I've encountered a similar failure, when some old process
           | still claimed [::]:80 when I restarted the web server,
           | probably a lingering socket or something like that, which
           | made the new process only bind to 0.0.0.0:80. It took me a
           | while to find out why my changes weren't being reflected when
           | I could see the binding _right there_ in `ss -tlpn`!
           | 
           | Honestly, I don't think it's too unreasonable to argue that
           | if a client has IPv6 connectivity and a hostname has a valid
           | AAAA record, the connection should be established over IPv6.
           | Browsers tend to have fallbacks to IPv4, but outside browsers
           | you'll be surprised how little actual system software cares
           | about DNS fallback.
           | 
           | Reading the BusyBox source code (https://elixir.bootlin.com/b
           | usybox/latest/source/libbb/xconn...) it seems like it will
           | pass AF_UNSPEC to str2sockaddr, which is packed into
           | `addrinfo hint` and then passed on to getaddrinfo(). Only
           | when IPv6 support is disabled or
           | ENABLE_FEATURE_PREFER_IPV4_ADDRESS is enabled will busybox
           | shuffle around the DNS results to return an IPv4 address.
           | 
           | If your service isn't available on IPv6 yet your hostname has
           | a valid IPv6 record, it's your task to indicate this to the
           | software (using the -4 flag, for example) or to configure it
           | to retry.
        
       | ajsnigrutin wrote:
       | > On Linux, you have multiple choices (wouldn't you know?), but
       | the easiest is to enter this in your terminal app:
       | 
       | > hostname -I                   $ hostname -I         hostname:
       | invalid option -- 'I'         Usage: hostname [-v] {hostname|-F
       | file}      set hostname (from file)            domainname [-v]
       | {nisdomain|-F file}   set NIS domainname (from file)
       | hostname [-v] [-d|-f|-s|-a|-i|-y|-n]  display formatted name
       | hostname [-v]                         display hostname
        
         | brycewray wrote:
         | Interesting. I used an alternate source[0] to check this and it
         | says the same thing I had in the article.
         | 
         | [0]: https://www.tecmint.com/hostname-command-examples-for-
         | linux/
        
         | rascul wrote:
         | Debian's hostname has -I. Turns out that's the hostname I have
         | here on openSUSE.
         | 
         | https://tracker.debian.org/pkg/hostname
        
           | Hello71 wrote:
           | there are at least four common implementations of "hostname"
           | on Linux: debian, coreutils, net-tools, busybox, and arguably
           | toybox. there are also at least four implementations of su
           | (util-linux, shadow, busybox, toybox) and five
           | implementations of kill (coreutils, procps(-ng), util-linux,
           | busybox, toybox).
        
             | ajsnigrutin wrote:
             | Yep, net-tools doesn't have the "-I" option
        
       ___________________________________________________________________
       (page generated 2022-04-02 23:01 UTC)