Jak hostować lokalny serwer za pomocą Heroku?

0

Chcę hostować witrynę Node.js uruchomioną na moim laptopie, aby była dostępna dla innych osób. Próbowałem przekierowania portów na routerze, ale to nie działa, ponieważ mój dostawca Internetu przestał udostępniać publiczny adres IP użytkownikom domowym. Innym rozwiązaniem, które mogę wymyślić, jest użycie Heroku do obsługi pewnego rodzaju odwrotnego proxy , za pomocą którego można uzyskać dostęp do strony internetowej.

Widziałem niektóre odwrotne proxy napisane w Go i Node.js w NPM , ale wydaje się, że używają one oddzielnych portów dla tunelu i serwera publicznego, na co Heroku nie zezwala . Mimo że Heroku zezwala tylko na jeden port, nadal uważam, że może istnieć kilka sposobów:

  • rozważ pierwszego użytkownika websocket jako klienta (strony internetowej).
  • uważaj użytkownika websocket z określonym adresem URL za klienta (stronę internetową).

Ponieważ możliwe jest, że wielu użytkowników łączy się jednocześnie z serwerem proxy, może być konieczne dołączenie identyfikatora do każdego żądania / odpowiedzi do klienta (strony internetowej).

Czy jest jakiś pakiet, który to zapewnia, lub w jakiś inny sposób, pozwala klientowi za NAT, nadal korzystając tylko z jednego portu?

wolfram77
źródło
Odwrotne proxy nie będzie działać, jeśli użytkownicy / proxy nie będą mogli nawiązać z Tobą połączenia.
Seth
Ale mogę się z nim połączyć, jeśli jest on hostowany w Heroku. Jestem nowy, ale jeśli zachowuje się jak tunel zwrotny SSH, myślę, że może działać.
wolfram77,
1
@Seth Próbowałem utworzyć proxy, najpierw próbowałem lokalnie z surowym tcp i działało lokalnie, ale nie w Heroku, więc zaktualizowałem kod symulując aktualizację HTTP i działa teraz! po wielu godzinach kodowania i błędów byłem w stanie uszczęśliwić Heroku. Odróżniam użytkowników od specjalnego klienta za pomocą tokena. Korzystam z mojego serwera lokalnie tutaj arproxy.herokuapp.com, a kod znajduje się tutaj github.com/wolfram77/node-rproxy .
wolfram77
Fajnie, możesz rozważyć opublikowanie go jako odpowiedzi na swoje pytanie i zaakceptowanie go. Jeśli uwzględnisz niektóre ze swoich badań, może to być naprawdę przydatna odpowiedź.
Seth

Odpowiedzi:

1

Zacząłem, jak sądzę, będąc dzieckiem, szukając sposobów na hostowanie publicznego serwera z lokalnego serwera w NPM . Szukano takich słów kluczowych jak:

  • Odwrotny serwer proxy
  • Tunel Ws
  • Odwrotny HTTP
  • Tunel TCP

Próbowałem ws-tunelu:
Potrzebny był osobny port do połączenia WebSocket i osobny port do hostowania serwera WWW . Mimo że w ten sposób mogło to działać, Heroku zezwoliło na użycie tylko 1 portu , a ja nie wiedziałem, czy jakikolwiek inny dostawca chmury zezwoliłby na 2 porty publiczne (czułem, że nie jest to możliwe).

Próbowałem reverse-http:
Może działać jako klient Reverse HTTP . Odwrotny HTTP to protokół dostarczany przez IETF. Ale potem potrzebowałem odwrotnego serwera HTTP . Jednak nadal występował problem ze zwrotnym HTTP , ponieważ mógł on przesyłać strumieniowo tylko jedno żądanie na raz . Było to w zasadzie połączenie HTTP w odwrotnej kolejności od serwera publicznego do lokalnego . Oznaczało to, że albo musiałbym w jakiś sposób serializować żądania wielu użytkowników do jednego lub wielu połączeń (wiele odwrotnych połączeń HTTP musiałoby zostać skonfigurowanych między serwerem lokalnym a serwerem publicznym ).

Spróbuj użyć pakietów TCP:
Wtedy zdałem sobie sprawę, że można to zrobić za pomocą jednego połączenia i prostszej niebuforowanej metody proxy. Odwrotny HTTP może wymagać buforowania, jeśli pojawiło się nowe połączenie i wszystkie połączenia odwrotnego HTTP były w użyciu. Rozważ użycie prostych pakietów o następującym formacie:

--------------------------------------
| Packet Size | Connection ID | Data |
--------------------------------------

Szukałem sposobu, aby to zrobić za pomocą WebSockets, jeśli miałyby jakąś istniejącą funkcję, której mógłbym użyć, ale wtedy zobaczyłem, że Heroku zezwala na dowolną aktualizację HTTP, więc zdecydowałem się na aktualizację TCP. Wiem, wymyśliłem to. Oto jak wygląda nagłówek, sprawdziłem, czy Heroku go akceptuje:

GET / HTTP/1.1
Upgrade: tcp
Connection: Upgrade
Origin: XXX

Ok, teraz pojawił się pomysł, jak zaktualizować połączenie między serwerem lokalnym a serwerem publicznym za pomocą protokołu TCP, a następnie komunikować się za pomocą pakietów. Nadal jednak format pakietu nie mówi nam, czy użytkownik się połączył, czy rozłączył. Mówi nam tylko, jakie dane użytkownik wysłał. Więc dodałem kolejne pole do pakietu:

----------------------------------------------
| Packet Size | Event | Connection ID | Data |
----------------------------------------------

Jednym z nierozwiązanych jeszcze problemów było rozróżnienie połączenia między użytkownikiem a serwerem lokalnym, ponieważ korzystamy z tego samego portu dla obu z nich. Można to zrobić na wiele sposobów, ale zdecydowałem się na konkretny User-Agentserwer lokalny.

Więcej wątpliwości, czy zbudować kod serwera publicznego za pomocą HTTP Node czy TCP Node. Tym razem czytałem o kodowaniu fragmentarycznym, zwiastunach i zdecydowałem, że lepiej będzie użyć TCP. Tak więc musiałbym przeanalizować początkowe żądanie połączenia i na podstawie określonego typu przetworzyć je jako użytkownik lub serwer lokalny. Ale wyobrażałem sobie, że wystąpi problem z wydajnością, ponieważ analizowałbym nagłówki HTTP każdego połączenia. Ale jeśli użyjemy rzadkiej metody HTTP do szybkiego rozróżnienia, na przykład HEAD, musielibyśmy odczytać tylko 4 znaki. Możemy więc teraz to zrobić:

1. If first 4 characters not HEAD, process as User.
2. Parse all the HTTP headers.
3. If User-Agent is special value, process as Local server
4. Process as User.

Dodałem także obsługę wielu kanałów, które mogą teraz umożliwić mi dostęp jako serwer SSH działający na innym komputerze (prywatny adres IP). Przeniesiłem kod i ozdobiłem README: https://github.com/nodef/rhost .

Kilka interesujących stron, które znalazłem podczas wyszukiwania:

wolfram77
źródło