Go-ipfs: Possible to only accept connections from a particular IPFS nodes?

Created on 19 Apr 2016  路  13Comments  路  Source: ipfs/go-ipfs

Is it, or will it ever be, possible to only accept connections from a particular IPFS node? Could this be used as a DDOS/anti-spam feature?

neecommunity-input

Most helpful comment

In the next couple months i'm going to be working on 'private networks' where you only accept connections from people who have a certain passcode. Would this suit your usecase?

All 13 comments

Yes but that would severely limit the usefulness of IPFS. Eventually, the bitswap protocol is supposed to have some sort of reputation system that should fix this. Basically, you'd prioritize nodes with good reputation over nodes with bad/unknown reputation.

In the next couple months i'm going to be working on 'private networks' where you only accept connections from people who have a certain passcode. Would this suit your usecase?

Just found this issue. I am also interested in having a decentralized private storage. I opened https://github.com/ipfs/faq/issues/128 few days ago, but no feedback so far. Private network assumes that peers accept connection requests only from trusted peers, and today it's not possible. Typically trust among parties is established by having a central authority trusted by all parties (e.g. root certificate authority in the TLS case), which then extends trust to other entities (e.g. by issuing certificates in the TLS case). The parties can exchange evidence that they are trusted by the central authority, and then they can trust each other.

From the operational point of view, it is usually very important that trust with the central authority can be revoked / renewed periodically (e.g. by expiring/reissuing/revoking certificates in the TLS case).

I know there are efforts underway around moving communication protocol to TLS, and perhaps some other efforts to improve trust between peers, but they seem to be very low priority. As I want to have something now, I came up with a simple trust solution that should be easy to implement. The central authority would be an application that holds information on all peers in the private network. Peers would have to register with the authority, so they can login there to pull information about all trusted peers. During secure connection handshake, a peer would expect to receive from the other peer a piece of evidence that the other party has indeed logged into the central authority (e.g. the peer's secret).

After looking at the code a bit, it seems to me this can be achieved by introducing two new concepts (interfaces):

  • BootstrapProvider
    -- default implementation would read the list of trusted peers from the local file, the same as now
    -- other implementations could read it from some REST service after logging into it
  • TrustManager
    -- It would be used by runHandshake() in protocol.go (go-lib-secio). Default implementation would keep doing what it is doing now.
    -- other implementations could check additional information (e.g. check the peer-specific secret that only the central authority knows) before continuing with handshake.

If this makes sense, I can put some time into it and create a pull request when done. To be blunt, I will do it anyways because I need it now, but I want to do it in a way that will be acceptable for inclusion into the official code base as I don't want to be in decentralized storage business.

Can someone provide feedback on this design and suggest changes so we can meet in trunk?

Of course, if you are already working on something similar and are close to finish, I would consider waiting for it.

I believe the correct way to do this is with access control and labels, not private networks (see MAC systems like SELinux and SMAC). When you add a file to IPFS, you would label it with "public" if you wanted the file to be public, $key/$label where only peers who have been authorized by $key to access data tagged by $label would be able to download the file, or nothing if you just want to add the file to IPFS but don't want to publish it yet. As labeled files are propagated through the network, the labels would be propagated with them. If a peer sees* the same file with two different labels, it would simply apply _both_ labels to the file allowing peers tagged with _either_ label to access the file.

This would allow peers to participate in any number of private networks at the same time while still maintaining security. Note: this proposal doesn't take privacy concerns into account (e.g., the ability to deny knowledge of a file)

This would also make it possible to simply put one's entire home directory in IPFS and not assign a label to anything (or assign a private label) to guarantee that one's files won't be shared. This would fix #875 (and be really cool).

*Currently, IPFS will avoid downloading the same file twice. To make this work, IPFS would either need to download the file again or implement some protocol for proving knowledge of a file. HASH($key/$label || File) should be sufficient proof that the file should be labeled with $key/$label and would even allow peers to serve files to private networks of which they are not members. Unfortunately, this does admit knowledge of the file so it might be better to just re-download the file in some cases (make this configurable per file/block?).

Hi @Stebalien , thanks for the reply. Yes, that would be a cool feature, enabling a whole bunch of cool use cases. But it is not exactly addressing the original ask (and my need). I don't fully understand implications of having the feature you are proposing and still allowing everyone to connect. First thing that comes to mind is that rogue peers could easily mount DOS attacks just by hitting the network with requests for non-existing data. There are probably many more ways to exploit the network openness. For easy sleep, I really need to allow only certain peers to connect.

I see; I misunderstood your intention. FYI, your node will only serve files you intentionally download/upload and/or pin so spam isn't really an issue. The real issue is denial of service through resource exhaustion.

To protect against unintentional DOS and misbehaving peers, IPFS will need some sort of QoS system (this is a planned part of bitswap). Unfortunately, there's really nothing you can do (without some help from your ISP) about malicious bandwidth-based DDOS attacks except to use some service like cloudflare. This is just a fundamental problem with the way the internet works. Even if you don't run IPFS, someone could still DOS your home connection easily*.

However, it still makes sense to provide some way of restricting who can connect to your node (especially on poor/metered connections). Even better, allow preferred nodes, and per-node bandwidth limits/preferential treatment.

*Unless something has changed since I last checked. This used to be a common way to take over IRC channels: DOS the operator, take elevate to operator, stop DOSing the operator. This obviously no longer works because IRC networks allow operators to own channels.

Peers would have to register with the authority, so they can login there to pull information about all trusted peers. During secure connection handshake, a peer would expect to receive from the other peer a piece of evidence that the other party has indeed logged into the central authority (e.g. the peer's secret).

This whole post was excellent, @alikic. But this part confused me. Wouldn't DOS-ing a secure connection handshake still be possible (just repeatedly spamming invalid credentials)? Is there any way a blockchain could help? I.e. a person pays a fee every time they try to make a connection.

Imagine a person who wants to buy data. Someone on the web owns this data and needs to be paid for it. The buyer posts a transaction on the blockchain to the seller, and includes in the transaction an amount of currency as well as a piece of data such as the buyer's IP address. The vendor's wallet software detects the transaction and then _initiates_ the secure connection with the buyer's IP, from an IP address / IPFS node known only to them (if this were on IPFS within a central authority, there would be multiple IP addresses associated with a file). Then it uploads the file to the buyer. This solves the problem of DOS for the vendor, yes? I suppose the buyer could be DOSed by anyone watching the blockchain at that time. Something like this would be useful for training machine learning algorithms over a blockchain. This is what I'm working on...

Hi @kevinmartinmauro , maybe I am missing something, but the solution you are proposing won't prevent a rogue IPFS peer which knows where the data is to steal it (as, as of today, an IPFS peer accepts connections from any other peer without restriction). Or you are proposing a layer on the top of the "private network" that deals only with DOS?

Hi @whyrusleeping, I'm interested in building 'private networks', even in the simplest form. Could I help with this feature? Where should I start if I would like to implement it on my own?

@alikic I would love to see working code if you have it. Has the IPFS team integrated any feature like this yet?

Hey everyone, experimental private networks support was merged for ipfs 0.4.7. Instructions on setting it up are here: https://github.com/ipfs/go-ipfs/issues/3397#issuecomment-284341649

Please try it out and let us know how it goes.

One step towards this would be to have the opposite of what was implemented for https://github.com/ipfs/go-ipfs/issues/1226, basically have in the config Swarm.AddrFilters but it works the reverse way, only allow connections that matches the filters.

This way, you can have nodes in a network who only accepts connections from within the network. Would be great to have for Guifi deployments (and other community networks I'm sure).

Edit: private networking won't work for the same use-case, as that requires previous knowledge of a shared secret. Having Swarm.AddrFilters (but reverse) would allow nodes to just join the network without having to find out about the secret.

Was this page helpful?
0 / 5 - 0 ratings