A fast and static web server for serving web apps
shortfin.io
shortfin.io
Just run the following command as root to install the server.
# wget http://shortfin.io/install.sh && sh install.sh
What? Are they serious? Is this becoming a thing? Please don't tell me that this is a thing.Then again, most of us blindly run what we assume to be GNU autoconf scripts and never read Makefiles before we 'make install' as root. Nor do most of us read or audit source code, even for security-sensitive applications.
The lack of TLS is worrisome, but that's not so much "becoming a thing" as it is "a bad thing we're just finally starting to get rid of."
Malicious compromise is not the only way that an install script can become broken, or corrupted, on a remote site. The ability to checksum what you're running is a very useful sanity check and you should be doing it with all downloaded scripts/packages.
I suppose this is tilting at windmills, though.
Yes, and you still can do that. But the standard installation instructions almost never include it. For example, nginx's build instructions boil down to "run configure, possibly with some flags, and then run make and/or make install". That includes the exact same vulnerability you complain of here — it never tells you to checksum anything. This is true for essentially all the software I've ever downloaded. So again, still not "becoming a thing."
The assumption is that if you're the sort of person who customarily checks code before they install it, you know how to inject that step.
Nginx is included in the OpenBSD base system (as of 5.2) and it does get vetted.
Well, getting the "trust us, this is easy" type installation instructions here isn't terribly comforting from a brand new project. That's the sort of thing I'd expect from a source I know. Not from this project that I didn't even know existed before this post.
It's unrealistic to expect those who take security seriously to do so in the first place. Regardless of how often it's done elsewhere.
OTOH, there's a well known and trusted software distributor that does the vetting for you, which this project doesn't have, and I'd much rather do the "vetting-skipped install" if you will for something they distribute instead.
Since I can't know everything that's running on my system, I'd trust that from some place that actually does vetting. It doesn't need to be OpenBSD, but some competent source with an established record for security.
That's not tautology. It's sane practice that I wish more people followed.
The wget/shell install as root is presumptuous in the extreme for a young project with no history. In fact, many young projects, whose security we know nothing about, have similar installations and that's a bad precedent to set and continue.
because you wouldn't use anything from him because he isn't OpenBSD
My sarcasm detector must be malfunctioning. Who said I don't want to use his software or install anything linked on HN because they're new? I've checked out and installed plenty of things linked on HN, not because they're new, but because they're interesting. But lax procedures like the root shell install aren't good indicators.In fact, I was just going over his install script to see whether it's worth installing and test, but seeing things like this :
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
-*) prefix='./';;
*) prefix='';;
esac
Is what makes me nervous.Oh, my apologies. I think the context of your other comments caused me to misunderstand that one. Your initial comment was simply "Nginx is part of the base OpenBSD install," and I read your later comment as an explanation of that, which made it sound to me like "I'm OK with nginx because it comes with OpenBSD and not OK with the OP's server because he's not a trusted organization." I understand better now.
And I apologize as well. My posts were venturing over to the pushy/rude side and I don't want that to be the case.
Truth is that I do enjoy seeing new projects like this because it forces me to look at things with a fresh perspective. Yes, the install method did give me some pause, but maybe I've been spoiled by things that I'm comfortable with so I welcome the chance to pour over the code for something totally different.
That said, if you're going to do this, you should do the following:
1. HTTPS only. No excuses.
2. No URL shorteners, which make or may not use HTTPS, and introduce another point of failure.
3. Ideally serve directly from Github repo. Eliminate another point of failure. The user can be reasonably confident that the install script is the same one that's in the Github repo.
For one, it's only requiring one simple script to get compromised and replaced to compromise your entire machine. At least when I download the tarball, unpack it, etc. I've got several steps before I even get to the make install that I would run as root. And I might not even do that depending on my install target. If I do, I have ample opportunity to verify the package in question and examine the script I'll be running via sudo before I do so.
With the instructions provided by this site, not only is there no opportunity to verify the script I've received is the one I wanted to (HTTPS alone is not enough for this, the site or domain may have been compromised) but they're instructing me to just run it immediately as root without any examination.
This is a terrible practice, and while yes it has been around for a long time in the past it was something only done and encouraged by idiots, it seems to be gaining popularity.
This is a bad idea, stop doing this people.
Provide an install tarball and provide a checksum of it that we can verify.
https://github.com/timothyej/Shortfin
My point was the people who are going to blindly run curl/sh commands are also going to blindly download the source tarball and run configure/make/make install, and the people who want to do more verification are certainly free to do so.
Unless curl or wget can confirm the sha1? Oh... found it! http://superuser.com/questions/453823/is-there-a-tool-that-a...
This has been standard practice for decades. It's very comprable to that wget oneliner. Why is it bad? Or, why is the wget oneliner bad but not Windows installers? Do Windows sysadmins compile tarballs and verify checksums? Or are Windows sysadmins simply dumber/less paranoid than Linux sysadmins?
It's a bad practice.
How would you then recommend installing non open source software on a production system? E.g. a freeware (but proprietary) FTP server or a database engine.
(Given that there are open-source and robuster-than-Windows platforms freely available.).
Suggesting that the best way to securely install Windows packages is to use a different operating system smacks of immaturity, and is obviously not a practical solution in Windows environments.
A better suggestion might be: If you do not trust it, run it in a VM/sandbox.
This protects you from a compromised package so long as the page you accessed the package from has not been compromised (if that page is compromised, the checksum could be changed to the new one).
I have no idea how you would verify closed source software if the checksum and package are both corrupted...
If the checksum is published to another trusted location, in addition to where you download the files, that would help in the case that an attacker compromises both the checksum and the package on the download site.
The developer could post the checksum to Twitter at the same time as making the package available for download. An attacker would need to compromise both Twitter and the download site.
This 100%.
When I first started experimenting with Linux after being a lifelong Windows user, this was the same advice I got from a seasoned Linux developer: ALWAYS COMPILE FROM SOURCE - NO EXCEPTIONS.
He just told me even though Linux is secure and not as big a target as MS, he said you want to establish good habits from day one and not get lulled into a false sense of security.
In fact, of all the install methods I use regularly as a Linux user, the only one that does not offer automatic checksums and public key signing is make. You can certainly verify checksums and public key signatures, but you have to do it manually.
Do you look through all the code you build from source? Highly unlikely. If not, what's the point?
Security is a lot more social screening than many people in the tech world would like to think. Know and trust the people you are running code from. If you don't know and trust them and still need their code, that's when you want to spend a couple of hours reviewing the source.
etc..
or do you want to tell us that you inspect every line of the source code before compiling something?
I can tell you I don't do this every time. Now if I'm installing a 3rd party extension or plugin, I usually do it in a sandboxed environment, run some pen tests on it to check how secure it is and see if there's any malicious code before I install it on my machine or server.
And yes, even then, it is still possible to install malware on your machine.
and later run it on some unprivileged TCP port over 1024.
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\binFrom a cursory glance:
1. https://github.com/timothyej/Shortfin/blob/master/src/reques...
should be (data_len - i >= 4) since it accesses data[i+3]
2. https://github.com/timothyej/Shortfin/blob/master/src/reques...
shouldn't headers[header_count]->key also be null terminated?
3. https://github.com/timothyej/Shortfin/blob/master/src/reques...
header_count can become greater than 49 which causes a heap overflow at https://github.com/timothyej/Shortfin/blob/master/src/reques... and https://github.com/timothyej/Shortfin/blob/master/src/reques...
as well as the header count (which i came here to post), there's another suspicious hard-coded size limit in the number of servers (1000). although you could only crash the system in that case by configuring too many.
there's very little error handling. good c code returns error codes all over the damn place. this hardly has any.
i wouldn't use this.
A webserver for only static pages, i.e. it won't talk to a runtime? But it's "for serving web apps", this means all the dynamic content is pulled from client side JS? Then you would still need programs on the server to answer AJAX requests.
I did not find an explanation on the page or by Googling.
A client-side JavaScript Twitter could be done this way. Every tweet, or timeline can be pre-baked into a static json file, and ajaxed in.
Twitter can then be simplified to a backend application that updates these files.
Granted, tweeting is a separate matter; that requires an endpoint that processes data.
In fact, I think the op needs to explicitly mention thttpd on the page for shortfin and provide a performance comparison, since that's all anyone really cares about ... "is it faster than thttpd ?"
What you're referring to is merely an observation about the actual capabilities of web servers in general at the time: "Most of these servers have enough oomph to keep a T1 saturated, running on a lowly 100MHz Pentium or maybe even a 486."
The trick is that most of the dynamic stuff you get from REST services on OTHER servers.
For example, people maintain static blogs with Jekyll and can enable commenting with an HTML widget.
Or your app can use MongoLab for it's back end data which again is a separate server.
It turns out you can do almost anything just developing with your own static files.
This is one of the reasons hosting prototype web apps on DropBox is popular.
Can add this to the list like thttpd.
Something I keep thinking I'll build is a fast, high connection count, limited HTTP server, something that is essentially a wrapper around a program that works like 'regular' and emits HTML. It is a corner case in a custom corner, but the target it something which is essentially a 'transponder.'
In the 'Internet of Things' I want to build a wrapper/environment such that my program can be
main(int argc, char *argv[]) {
uint16_t sense;
uint16_t chan;
sense = adc_read(atoi(argv[1]));
printf("Sensor %d reads : %d\n", chan, sense);
}
And then link my 'wrap around web server on it' and then it can be accessed with wget 'http://ip:port/?1' have it do the right thing.The keys are low memory footprint, lots of connections, easily wrapped around a 'regular' program.
Sounds like you want CGI :)
HTML isn't that big, so if you used linked resources, it would be pretty simple to make a C program and compile it to a binary for any purely "static" site.
But like you say, I have to wonder if it actually makes a difference performance-wise. The kernel will cache the static file data anyways. The only improvement I can see is maybe to avoid having to look up file metadata (length and mtime)? Or to avoid a syscall?
As long as you have a web server that can load modules and be invoked on specific URL requests, you can embed this.
Basically FastCGI is like having another server just for your dynamic content while the web server sits in front of it and takes care of hosting the static content and deferring to the FastCGI server when appropriate.
Luckily, there's already code for that, in case you're interested : http://arduino.cc/en/Tutorial/WebServer
Having HN crowd coming and testing your server would be a great test, no?
> It was created in 2011 by Timothy E. Johansson and is the base for the send-API and the tracking server for AlphaMail.
> It also powers this website (though behind nginx). You can reach it directly on port 88: shortfin.io:88
What's the point in using this if you're going to have nginx in front?
I mean, what's the main "selling point". Why should one use this instead of battle tested nginx?
Don't get me wrong, I'm not criticizing, I'm just curious.
There isn't any "selling point" ;) Anyone could use it as they like. The main usage for me has been in other projects where I needed a fast and lightweight http server. Such as tracking servers etc. It's pretty "experimental" but I think I will use the "original" server to serve a web app that I will be launching soon. The problem for me has been the lack of a reverse proxy.
The answer to "why" is answered in these comments:
https://news.ycombinator.com/item?id=6168052 https://news.ycombinator.com/item?id=6168541
Then I thought may be I was being a little bit to picky and unfair, so I checked the code of some random files and... well, it looks like it was part of a learning experience but it definitely needs work before being considered a viable option.
Isn't it recommended that any project doing one-line installs use HTTPS?
$ curl http://shortfin.io/install.sh | sh
I definitely agree with the HTTPS. For example this is what meteor proposes: $ curl https://install.meteor.com | shStreaming your install script directly into computer execution without even giving it a once-over, md5 compare, etc is atrociously insecure.
curl https://install.meteor.com | less1. First Test is using http://www.webpagetest.org/
Results shortfin.io:88 - http://www.webpagetest.org/result/130806_71_13HK/
First View: 1.945s
Repeat View: 1.632s
Results shortfin.io - http://www.webpagetest.org/result/130806_QV_13F7/ First View 2.099s
Repeat View 0.084s
2. Second Test is using Apache BenchResults (Best results of 3 runs): ab -n 100 -c 100 http://shortfin.io:88/
Time taken for tests: 12.125 seconds
Requests per second: 8.25 [#/sec] (mean)
Time per request: 12124.501 [ms] (mean)
Time per request: 121.245 [ms] (mean, across all concurrent requests)
Transfer rate: 38.46 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 210 1114 1517.2 360 4041
Processing: 5017 8407 2034.0 8715 11762
Waiting: 169 1084 3054.8 188 11408
Total: 9057 9521 1068.7 9058 12123
Results (Best results of 3 runs): ab -n 100 -c 100 http://shortfin.io/ Time taken for tests: 5.790 seconds
Requests per second: 17.27 [#/sec] (mean)
Time per request: 5789.949 [ms] (mean)
Time per request: 57.899 [ms] (mean, across all concurrent requests)
Transfer rate: 82.97 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 171 249 35.7 263 290
Processing: 172 1798 2345.5 212 5524
Waiting: 170 1055 1825.1 212 4949
Total: 344 2047 2368.2 469 5789$ ab -n 100 -c 100 http://shortfin.io/
Requests per second: 1363.85 [#/sec] (mean)
You're basically benchmarking your internet connection.
Why Shortfin when we have Nginx/Lighttpd?
Why Shortfin when we have thttpd?
2. See #1.
3. I don't try to sell anything, it's just an open-source project that I think maybe someone could benefit from. I've learned a lot while coding it.
Well, let a hundred flowers blossom.
The wget shell script installation does make me nervous and I'm glad the source is available separately. Blind installation of scripts was never "a thing" with me.
Of course, I'm still glad people are writing proper web servers (as opposed to simple 2-10 line ones). That creates an opportunity to explore the field with fresh ideas.
No explanation of what the configs are, just that "its important to configure it right."
Why not put this information on the site?
https://github.com/timothyej/Shortfin/blob/master/src/respon...
I am not sure what's the point of using it instead of nginx.
By the way, can you show some statistics and performance metrics with respect to nginx, Apache and such?
To put it another way: why did you choose to write your own webserver instead of using, say, nginx?
I will perform some benchmarks and compare it to nginx (and maybe apache) in a while.
By the time (2010, 2011) I was working at a company that needed a tracking server for tracking clicks and views in email. So I started to mod lighttpd and thought that I could make it faster. So in true "challenge accepted" spirit I started to write my own HTTP server. And since then I've made it better and better. It's not meant to be an nginx killer. It will always be very basic, fast and lightweight. It's great for projects where you need a web server included.
As I wrote in another comment I have used the code base myself in various projects such as:
* Tracking clicks, view, etc. for AlphaMail * The send-API server for AlphaMail * A DMARC report server (https://github.com/amail/comfirm-dmarc-report-server) * A REST server with redis as storage
I've never used it as a static web server in production yet. Mostly because of the lack of a reverse proxy and other great features that nginx has and shortfin not.
The author claims it's 'high-performance and open-source' - sounds good to me. It's not as if we have a hundred web servers all competing as we do static blogging systems, the more web servers the better in my opinion, just as with web browsers.
The zip file is 312KB as linked from here, so it's pretty compact, possibly suitable for embedding in apps, etc:
tl;dr:
Shortfin: 18 914 req/sec
Nginx: 15 603 req/sec
SHORTFIN
sudo ab -n 100 -c 100 http://127.0.0.1:40/timothy-johansson.png
Server Software: shortfin/0.9.5
Server Hostname: 127.0.0.1
Server Port: 40
Document Path: /timothy-johansson.png
Document Length: 56089 bytes
Concurrency Level: 100
Time taken for tests: 0.005 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 5618000 bytes
HTML transferred: 5608900 bytes
Requests per second: 18914.32 [#/sec] (mean)
Time per request: 5.287 [ms] (mean)
Time per request: 0.053 [ms] (mean, across all concurrent requests)
Transfer rate: 1037701.56 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 0.0 1 2
Processing: 2 2 0.1 2 2
Waiting: 1 1 0.2 1 2
Total: 4 4 0.1 4 4
ERROR: The median and mean for the initial connection time are more than twice the standard
deviation apart. These results are NOT reliable.
Percentage of the requests served within a certain time (ms)
50% 4
66% 4
75% 4
80% 4
90% 4
95% 4
98% 4
99% 4
100% 4 (longest request)
NGINX sudo ab -n 100 -c 100 http://127.0.0.1:41/timothy-johansson.png
Server Software: nginx/1.2.6
Server Hostname: 127.0.0.1
Server Port: 41
Document Path: /timothy-johansson.png
Document Length: 56089 bytes
Concurrency Level: 100
Time taken for tests: 0.006 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 5631000 bytes
HTML transferred: 5608900 bytes
Requests per second: 15603.06 [#/sec] (mean)
Time per request: 6.409 [ms] (mean)
Time per request: 0.064 [ms] (mean, across all concurrent requests)
Transfer rate: 858015.83 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 0.7 2 3
Processing: 1 2 0.5 1 3
Waiting: 0 1 0.7 1 3
Total: 2 4 0.9 4 5
WARNING: The median and mean for the processing time are not within a normal deviation
These results are probably not that reliable.
Percentage of the requests served within a certain time (ms)
50% 4
66% 4
75% 4
80% 4
90% 5
95% 5
98% 5
99% 5
100% 5 (longest request)I understand the desire to get software out there, but webserver is a ridiculously hard nut to crack. nginx broke in through a new architectural paradigm.
Keep it up!