A HTTP3 web server for reverse proxy and single page application, automatically apply for ssl certificate, zero-configuration.
❤️ A project by txthinking.com
Install via nami
$ nami install nico
Make sure your domains are already resolved to your server IP and open 80/443 port
$ nico domain.com /path/to/web/root
$ nico domain.com http://127.0.0.1:2020
$ nico domain.com https://reactjs.org
- Exact match: domain.com/ws
- Prefix match: when / is suffix, domain.com/api/. A special one: domain.com/ is exact match
- Default match: domain.com
$ nico domain.com /path/to/web/root domain.com/ws http://127.0.0.1:9999 domain.com/api/ http://127.0.0.1:2020
$ nico domain0.com /path/to/web/root domain1.com /another/web/root domain1.com/ws http://127.0.0.1:9999 domain1.com/api/ http://127.0.0.1:2020
NICO_TCP_FALLBACK lets a service that does not speak TLS, such as
dsvpn, share the port nico serves HTTPS
on. Each accepted TCP connection is classified by its first bytes: connections
that start with a TLS handshake record (0x16 0x03, valid record version and
length) are served by nico as usual, everything else is relayed byte-for-byte
to the fallback address. HTTP/3 (UDP) is not affected.
# dsvpn listens on loopback only, so it is reachable only through nico
$ sudo ./dsvpn server vpn.key 127.0.0.1 1959
# the website keeps working on https://domain.com:443, and dsvpn clients
# connect to domain.com:443 as well
$ NICO_TCP_FALLBACK=127.0.0.1:1959 nico domain.com /path/to/web/root
Active probers sending a TLS ClientHello reach the real website; probers
sending anything else reach the fallback service, which drops them. dsvpn is a
point-to-point VPN for a single client, and behind the fallback every client
appears to come from 127.0.0.1, so run one client at a time.
Note that the fallback stream itself is still plain TCP: this hides the VPN behind a normal-looking HTTPS port, but a network that refuses non-TLS bytes on port 443 will still block it. The next section covers the TLS variant.
NICO_TLS_FALLBACK is the stealthier variant. nico terminates TLS itself with
the site's own certificate, then inspects the decrypted stream: HTTP requests
are served as usual, everything else is relayed to the fallback address. On the
wire this is ordinary TLS to your own site name, so there is no "port 443 but
not TLS" signature and no dedicated VPN name in the SNI to block. The client
must wrap its traffic in TLS, must not negotiate the h2 ALPN protocol, and
should use the site's own name as SNI.
# dsvpn listens on loopback only
$ sudo ./dsvpn server vpn.key 127.0.0.1 1959
$ NICO_TLS_FALLBACK=127.0.0.1:1959 nico domain.com /path/to/web/root
Desktop client with stunnel, then point dsvpn at 127.0.0.1:1959:
[vpn]
client = yes
accept = 127.0.0.1:1959
connect = domain.com:443
sni = domain.comHow the decrypted stream is classified: ALPN h2 is always treated as HTTP;
otherwise the first bytes are compared against HTTP request methods (and the
HTTP/2 preface). A fallback payload that starts like GET would be
misrouted, so the tunnelled protocol must not look like HTTP.
Both fallbacks can be enabled at once, so plain-TCP clients keep working while
you migrate; prefer NICO_TLS_FALLBACK when the network inspects protocols.
You may like joker
Nico is a simple HTTP3 web server, but she is enough in most cases. If you want to use rewrite, load balancing, you need to consider nginx or others.
Licensed under The GPLv3 License