
Ffsend – Share Files from the CLI: A Firefox Send Client Written in Rust - hugodutka
https://gitlab.com/timvisee/ffsend
======
cyphar
Another really neat solution to sending data between two machines that don't
have a pre-existing channel is magic-wormhole[1]. It's much simpler because
it's just a number and some easy-to-distinquish code words like 1-stethoscope-
zulu.

[1]: [https://github.com/warner/magic-
wormhole](https://github.com/warner/magic-wormhole)

~~~
twoodfin
Very cool!

I dove in to see how they solve the routing / firewall problem. Turns out
you’re relying on the kindness of strangers and a public WebSocket relay. Hard
to see how they could do any better, alas.

IMO one of the big holes in the architecture of the web is the lack of a
standard peer-to-peer “content-addressable routing” protocol, perhaps based on
any of a number of distributed hash table schemes. It’d be perfect for
something like this.

~~~
noman-land
Far from a standard but have you checked out libp2p? It's pretty far along as
a modular p2p networking util.

[https://libp2p.io/](https://libp2p.io/)

~~~
twoodfin
Excellent! Yeah, I often daydream about a web where something very much like
that had become foundational.

Unfortunately, the academic work on DHTs emerged at around the same time as
both the stultifying dominance of Internet Explorer and the panic over Napster
_et al_.

------
timvisee
Developer here. Thanks for posting! Feel free to ask my any questions.

~~~
jeltz
Upload is very slow for me, about 40 kB/s compared to the about 400 kB/s I get
with scp. Is that normal?

Edit: It seems equally slow to me when using the website, so I suspect the
issue is with Mozilla's sever, not the client.

~~~
timvisee
If might be because of slow cryptography, that isn't hardware accelerated.
What system are you running on? I can easily reach 20MB/s.

~~~
jeltz
Feels too slow even for slow cyrpto. I suspect either that I am rate limited
by the server or there is some bug somewhere.

CPU: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz

Kernel: Linux 4.19.0-6-amd64

Distro: Debian 10.2

Rust: rustc 1.40.0 (73528e339 2019-12-16)

Program: ffsend 0.2.57

~~~
timvisee
That should definitely work fine, yeah! I'm assuming it has to do with the
network or their server as well. Sorry I can't be of much help.

------
mschwaig
I mostly use Firefox Send to transmit data between my own devices and devices
I do not trust. I wish the web client could generate QR codes to make that
easier.

Probably I could combine Fsend and another CLI tool to enable that use case.
Right now I'm manually typing links into different devices.

EDIT: Fsend can do this by itself!

~~~
timvisee
Just want to note that QR code generation is a feature in `ffsend`. Simply use
the `-Q` flag while uploading.

~~~
mschwaig
Wow, that's great! Thanks.

------
thrwaway69
That's pretty neat. Currently I use dat, resync or ipfs to move big files
around on CLI. Maybe I will try this next time I wanna share big files.

Obligatory web alternatives that are peer to peer -

[1]: [https://github.com/kern/file.pizza](https://github.com/kern/file.pizza)

[https://file.pizza](https://file.pizza)

[2]:
[https://github.com/cowbell/sharedrop](https://github.com/cowbell/sharedrop)

[https://sharedrop.io](https://sharedrop.io)

[3]:
[https://github.com/webtorrent/instant.io](https://github.com/webtorrent/instant.io)

[https://instant.io](https://instant.io)

[4]:
[https://github.com/RobinLinus/snapdrop](https://github.com/RobinLinus/snapdrop)

[https://snapdrop.net](https://snapdrop.net)

------
duckerude
I like that this removes some of the need to trust the service. When you open
a link in a browser it's tedious to verify that the webpage doesn't send the
secret to anyone, but this way you only have to trust the command line tool,
which can't be replaced unpredictably.

------
archie2
Somebody that knows zilch about Rust with a question: I like to write CLI
tools with Go, the built-in libs and the simpleness of the language make it
really easy for writing good tools quickly. What advantages does Rust have
over Go that one would use it for this purpose?

~~~
PrototypeNM1
I don't know the current state of go package management but I do know the
equivalent Go project cited Rust's package manager Cargo as a good reference
for developing their own. You forget Rust's standard library is quite
minimalist and you get to sample competing libraries which often use
interchangeable interfaces. In particular there are several crates (libraries)
which make handling CLI arguments convenient.

If your code is stateful the typestate pattern is particularly easy to write
in Rust - [http://cliffle.com/blog/rust-
typestate/](http://cliffle.com/blog/rust-typestate/)

~~~
archie2
I've never heard of the TypeState Pattern, thanks for the link and it even got
me interested in getting to know more about Rust. Thanks a bunch!

------
api
It's 2020. Is it finally possible to send a file over the Internet directly
from one machine to another?

Only if you are not behind symmetric NAT I suppose.

Tangent: why does symmetric NAT exist? It seems like the kind of thing
firewall fetishists do "for security" without considering the problems it
causes and without any clue of what sort of attack it thwarts that mere
stateful firewalling does not thwart.

Realize that without symmetric NAT, TURN would be largely unnecessary.

~~~
johnisgood
I am pretty sure there are many people on here who have not forgotten (it is
not even that old! :P) and still use any variations of netcat, or even rsync.
Nmap's Ncat is cross-platform (I use MSYS2 on Windows so it does not matter
much to me), supports SSL, proxies, connection brokering, and a lot of other
stuff[1][2].

[1] [https://nmap.org/ncat/guide/](https://nmap.org/ncat/guide/)

[2]
[https://en.wikipedia.org/wiki/Netcat#ncat](https://en.wikipedia.org/wiki/Netcat#ncat)

~~~
api
All that stuff doesn't work between systems behind firewalls or NATs.

~~~
johnisgood
> A basic file transfer is very simple: Start Ncat in listen mode on one end,
> start Ncat in connect mode on the other end, and pipe the file over the
> connection. There are two ways to do this that differ only in which end
> listens, the sender or the receiver. Sometimes you can't create a listening
> socket on one end of the transfer because of a lack or permissions, NAT, or
> filtering. As long as you can listen on at least one end, though, you can
> use this technique.[1]

This works with most if not all netcat implementations.

> The basic file transmission technique described at the beginning of this
> section fails if neither participating host is capable of listening, or the
> two hosts can't communicate directly. This situation has become common with
> the prevalence of network address translation. A way to work around it is to
> use a third host as an intermediary. The intermediate host listens in
> connection brokering mode and the other two hosts connect to it. Recall from
> the section called “Connection Brokering” that in connection brokering mode
> any input received on one socket is copied and sent out to all other
> sockets. With just two hosts connected this is especially simple: anything
> coming from one host gets forwarded to the other. This example shows host1
> sending inputfile to outputfile on host2, using host3 as an intermediary.[1]

This works nicely with Nmap's Ncat.

[1] [https://nmap.org/ncat/guide/ncat-file-
transfer.html](https://nmap.org/ncat/guide/ncat-file-transfer.html)

~~~
api
The second is not direct.

------
anderspitman
I'll go ahead and plug [https://patchbay.pub](https://patchbay.pub) here. If
you're somewhat less concerned about having encryption, you can do CLI
transfers of files of arbitrary size without installing anything (assuming you
have an HTTP client like curl already), and without needing an account:

Sender:

curl [https://patchbay.pub/random-channel-chosen-by-
you](https://patchbay.pub/random-channel-chosen-by-you) \--data-binary
@file.mp4

Receiver:

curl [https://patchbay.pub/random-channel-chosen-by-
you](https://patchbay.pub/random-channel-chosen-by-you)

As mentioned by others, [https://file.pizza](https://file.pizza) is great if
both devices have browsers, and the WebRTC connection between them succeeds.

~~~
rakoo
Your service sends everything through the instance so we rely on the bandwidth
you're willing to share. It already is amazing, but the same thing through
WebRTC would be really great. I know it means work would mostly be on the
client side though, and curl wouldn't be enough anymore

------
heyflyguy
These are all very interesting, I am currently facing an issue getting
BitTorrent file transfer to pierce an "unfriendly" firewall that I can't
change permissions on. I've tried a VPN out with no luck. I wish I knew if one
of these would allow me to get out.

~~~
kibwen
Firefox Send is a web page, so if you can access the web you can use it. Also,
a firewall that you can access the web from will have ports 80 (http) and 443
(https) open, so configure your tools to use one of those (preferably 443). If
both machines are standard internet-facing Unix-likes that you have accounts
on, you'll already have scp preinstalled for easy file transfer.

~~~
sudosysgen
Many modern firewalls do Deep Packet Inspection, so obfuscation might be
needed too.

~~~
kibwen
As long as your traffic is encrypted (which ssh/scp is) and as long as your
machine isn't compromised then a firewall can tell so little about your
traffic that it would have to be pretty paranoid to attempt to block any of
it. It'll work at a Starbucks, but perhaps not in China.

~~~
sudosysgen
Deep packet inspection will almost invariably be able to recognize ssh/scp
from the packet sizes, the patterns, the ports and so on. You really do need
some kind of obfuscation. Starbucks won't catch it, but I know for a fact my
former high school does, for example.

------
uberneo
few more similar (python based) command line options for Firefox Send -
[https://github.com/nneonneo/ffsend](https://github.com/nneonneo/ffsend) &
[https://github.com/ehuggett/send-cli](https://github.com/ehuggett/send-cli)

Would be great to have something like curl -X POST @myFilePath
"[https://api.send.firefox.com"](https://api.send.firefox.com")

------
sdan
Looks cool! Personally, however, I’ve been using croc
([https://github.com/schollz/croc](https://github.com/schollz/croc)) and can’t
recommend it enough. I use it almost on a daily basis and is a super easy file
transfer tool.

~~~
cyphar
It's crazy how incredibly similar to magic-wormhole[1] this looks.

EDIT: Ah, they mention magic-wormhole in the acknowledgements as being an
inspiration.

[1]: [https://github.com/warner/magic-
wormhole](https://github.com/warner/magic-wormhole)

~~~
qrv3w
Yeah, I made croc because wormhole wasn't easy to install on Windows and
wormhole also doesn't support resuming transfers.

------
msravi
termux + woof

woof -i <ip_address> -p <port> <filename>

termux:
[https://play.google.com/store/apps/details?id=com.termux](https://play.google.com/store/apps/details?id=com.termux)

woof: [http://www.home.unix-ag.org/simon/woof.html](http://www.home.unix-
ag.org/simon/woof.html)

1\. Allows directory upload/download (tar/gzip/bzip2 compressed)

2\. Local file server (doesn't need to go over the internet)

3\. Allows upload form (-U option)

4\. Allows file to be served <count> number of times (-c option)

------
jedisct1
What does the fact that it's written in Rust do? Do we get more storage space?
Can files being downloaded faster?

~~~
megous
Nothing. You can get the same secure sharing service with zero hassle with a
simple shell script:

    
    
        sum=$(sha1sum "$1" | cut -f 1 -d ' ')
        ssh your-vps mkdir /srv/http/files/$sum
        scp "$1" your-vps:/srv/http/files/$sum/
        echo https://your-vps/files/$sum/$1
    

\+ nginx or whatever

~~~
rvz
Well I can't use this on Windows nor can I guarantee that this cryptic shell
script will run on my friends computer who still uses Windows. Even so, he
wouldn't know how to run it.

Also it can't be a "secure sharing service" if you're still using 'sha1sum'
and it not being end-to-end encrypted...

~~~
megous
So use sha256sum, if you don't trust SHA1.

Also it's quite secure since file content is clearly mapped to the URL you're
sharing with the other party via independent channel and the receiving party
can verify the content of the file.

It may not be completely private if VPS does not run on your own HW, but
nothing prevents you from running it on your own HW in your secured location.

You can use this on windows the same way you'd use it on Linux. You just
install a bunch of programs and run commands from command line. (basically
just like you'd need to do with fsend) It's less hassle on Linux, since the
commands are pre-installed. Fsend is more hassle on Linux since it's not
preinstalled and requires rust, compilation, etc.

The other people just open a https links and download files in any browser or
via curl, no tools required at all, not even JS.

------
wildduck
Or with python just going to dir you want to share:

python 2.7 >python -m SimpleHTTPServer 8080

python 3 > python -m http.server 8080

~~~
matthewmacleod
You can also recreate Dropbox just by combining an FTP Server with curlftpfs
and SVN :)

Python’s built-in HTTP server is pretty useful. It doesn’t really overlap with
the functionality of use-cases of a Send client much at all.

