Score:-2

macOS: How do I expose a localhost port to the LAN IP on the same computer?

br flag

On a Raspberry PI I have, whatever I run on, say, http://localhost:8080, is automatically visible to other computers on my local network at http://192.168.0.xxx:8080 or http://pi.local:8080.

This doesn't happen with my Mac. If I'm testing an Angular app which runs on http://localhost:4200, that app will not be seen at http://mymac.local:4200 by other computers on my local network.

All I want to do is expose the localhost port to my LAN, not to the rest of the world. Yet when I look for a solution to this problem, all I turn up is tools like ngrok, which isn't what I want. I'm not trying to have my app visible to the whole world, just my LAN.

My macOS firewall is not turned on, so there is not a problem as far as I know with the particular port being actively blocked.

UPDATE:

A make-shift solution I have found is this:

browser-sync start --proxy "localhost:4200" --no-open --no-ghost-mode --no-notify --no-snippet --no-ui --port 4200

browser-sync, however, is specifically HTTP oriented, and tries to mess around with the contents which are served in many way, hence all of the --no-xxx flags I'm using. I'd like to find a similar, simpler solution that forwards TCP traffic in a purely neutral way.

dexter avatar
ru flag
Is application running on Mac reachable on `http://mymac.local:4200`?
kshetline avatar
br flag
@dexter, no, it isn't, but that's what I want to have happen, while also keeping the app visible on localhost at the same time.
dexter avatar
ru flag
I asked that because port numbers differs, you said Angular runs app on port 4200 and you are trying to reach it on the port 8080. If you don't have some routing I don't see how it can work. Check on which `IP:PORT` app is listening on Mac (`ss` or `netstat`, not sue what is there on Mac ).
kshetline avatar
br flag
@dexter, sorry about that! It was merely a typo that I repeated 8080 describing the second case. I want localhost:4200 to also be seen at mymac.local:4200.
vidarlo avatar
ar flag
According to comments on my answer this is not about Angular, but Elasticsearch in Docker. Can you [edit] your question to reflect your *actual* problem, so it's possible to answer?
Score:1
cn flag

If the service running is specifically bound to use loopback as a listen interface, such as hardcoded and you do not control the source. Dynamic straightforward an ssh tunnel for instance.

Use socat https://stackoverflow.com/questions/16808543/install-socat-on-mac

Check out the help documentation, you can choose protocols, interfaces to bind to, etc, and a host of other things.

SOCAT rocks....

socat TCP-LISTEN:8080,fork TCP:127.0.1:8888

kshetline avatar
br flag
Thank you for answering my actual question, instead of giving me a hard time for not asking it in exactly the right way.
Sabre avatar
cn flag
Quite welcome, if the answer works for your needs. You can accept it as *the* answer. There are many ways to do the same type of relay you are doing, if socat does not work out you could use HAproxy as well since you are using http, with the frontend on your LAN int, the backend being localhost. That would be a more formal "Service" approach, if you want this to be persistent. However wrapping socat up as a service works flawlessly as well, I have used it many times to expose things like a dynamic port forwarding socks proxy over SSH, or MITM another service for analysis.
Score:1
ar flag

On a Raspberry PI I have, whatever I run on, say, http://localhost:8080, is automatically visible to other computers on my local network at http://192.168.0.xxx:8080 or http://pi.local:8080.

No, you don't. Linux, like all other modern operating systems, has the concept of where you're listening. This is called interface binding. Windows, Darwin, Linux and all other modern operating systems supports this, and it essentially let's you specify on what interface you want to listen. Maybe you want Apache to listen to 203.0.113.1, and nginx on 203.0.113.2? If so, you can specify this in the config files.

This is commonly used when you want something to only be available locally: you tell it to bind to 127.0.0.1, or ::1, which is the loop back address. This will not be reachable from any other host, as it's bound to the loop back interface only.

There's also a catch all: 0.0.0.0, or :: in IPv6 parlance: bind any available interface. This will listen on all enabled interfaces, including loop back and others.

In short: figure out how the service you're using defines network interface bind, and modify it to fit.

kshetline avatar
br flag
Perhaps there's some magic going on behind the scenes of which I am unaware, but my Raspberry Pi project is a simple Node.js Express app, set up to listen on one particular port via `httpServer.listen(httpPort);` I have certainly made no effort to bind to any particular interface. I simply let Express do its thing. The server is then available on both localhost and the LAN, through no special effort of my own.
vidarlo avatar
ar flag
If the same config produces different results on different computers, then the implementations differ or there's a firewall.
kshetline avatar
br flag
it's not the same app I'm trying to do this with now, but the same app on the two different computers has produced the results as described, and my firewall is off. At any rate, I really don't care why the problem exists, I simply want a solution that will create an appropriate tunnel without changing anything about any app -- the particular app I'm trying to expose now being an instance of ElasticSearch running on Docker than I want available on both localhost and the LAN without messing with the ElasticSearch setup.
vidarlo avatar
ar flag
Then ask why ES hosted in docker on Darwin is NOT working. Don't ask about a node.js app! Show us the docker config or docker-compose files you're using! My answer is perfectly valid for the question you asked, but you asked a question which was *not* related to your problem. And it's not about tunneling. It's about interfaces and binding, and possibly port forwarding in case of docker.
kshetline avatar
br flag
my question made it perfectly clear what end result I wanted. I can't help it if you got fixated on the example I used to illustrate the final result that I wanted. I'll take it you're the one who down-voted my question for the sin of not expressing my problem to your satisfaction.
vidarlo avatar
ar flag
I downvoted it, yes. My answer answers what your question was before edits, by explaining how interface binding works. Docker brings network namespaces into the mix, and uses masquerading to hide internal things, thus it's not valid for a docker setup. A good rule is to ask what you're wondering about, which as much detail as possible. Now I spent time writing an answer to something you didn't want answered, and I find that behavior by you rude.
kshetline avatar
br flag
My question was "macOS: How do I expose a localhost port to the LAN IP on the same computer?", before any edits, not "How do I change this app to bind to my LAN instead of localhost?", which is was you appeared compelled to answer, by rudely insisting that what I said was happening wasn't even happening. I'm not an expert on networking, which is why I asked a question here. You apparently have little or no tolerance for someone who dares ask a question other than the way you think it should be asked. And you accuse me of rudeness?
vidarlo avatar
ar flag
I explained how interface binding works, as I suspected you were unaware of this. Interface binding is your problem as the question stands, with firewalls disabled. You can continue quarreling, or you can read the relevant documentation for the application you're using to figure out how to bind to 0.0.0.0. Incidentially, the other answer also points to interface binding, and provides a workaround if your application is unable to configure this. In most cases it's better to reconfigure your application than using socat...
kshetline avatar
br flag
"No, you don't." is not the start of helpful advice. And you were wrong too. What I said was happening was happening -- app visible on localhost and LAN, without any special effort on my part -- even if I was unaware of how it was happening.
vidarlo avatar
ar flag
Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/140580/discussion-between-vidarlo-and-kshetline).
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.