dtn7 / dtn7-rs

Rust implementation of a DTN based on RFC 9171
Other
75 stars 20 forks source link

403 Forbidden on to /peers/add request #56

Closed iwojim0 closed 7 months ago

iwojim0 commented 7 months ago

got "403 Forbidden" on to /peers/add request in case of deploiment dtn7-rs behind nginx reverse proxy. it looks as some restricted access on http server level.

11:47:19.248652 IP 192.168.1.103.48400 > 192.168.2.253.3000: Flags [P.], seq 1:328, ack 1, win 502, options [nop,nop,TS val 1750326081 ecr 2108452123], length 327 E..{..@.=......g........PR._-.k.....I...... hS.A}.m.GET /peers/add?p=http://dtn7-node2.my-dtn7-rs.onion:3000/node2&p_t=STATIC HTTP/1.0 Host: dtn7-node3.my-dtn7-rs.onion:3000 X-Forwarded-For: 127.0.0.1 X-Forwarded-Proto: http Connection: close User-Agent: curl/8.5.0 Accept: /

11:47:19.248746 IP 192.168.2.253.3000 > 192.168.1.103.48400: Flags [.], ack 328, win 507, options [nop,nop,TS val 2108452153 ecr 1750326081], length 0 E..4..@.@..........g....-.k.PR............ }.m9hS.A 11:47:19.249683 IP 192.168.2.253.3000 > 192.168.1.103.48400: Flags [P.], seq 1:83, ack 328, win 507, options [nop,nop,TS val 2108452154 ecr 1750326081], length 82 E.....@.@..W.......g....-.k.PR............ }.m:hS.AHTTP/1.0 403 Forbidden content-length: 0 date: Mon, 29 Jan 2024 11:47:19 GMT

iwojim0 commented 7 months ago

after that fix https://github.com/iwojim0/dtn7-rs/commit/96413dd931521ca12dd1a1f2589d9c5e2aa79fc5 all work fine

gh0st42 commented 7 months ago

This is not a bug but a (security) feature. Putting the endpoints for add and delete outside of app_local_only is a really bad idea. Now they are totally unprotected and anyone can add external peers to your node and use this for DoS attacks or worse.

If you really must access these URLs from an external source you should rewrite them from the proxy to appear to be coming from localhost. Another alternative would be to have your own command and control server running, python flask or similar, that then opens a local connection or runs a curl script.

iwojim0 commented 7 months ago

This is not a bug but a (security) feature. got it, however (from working in i2p/tor overlay networks perspective) this is security feature will not work as your planed - because all incoming connections to opened hidden service will look (for this service) as local (in case if both started on one host).

iwojim0 commented 7 months ago

Another alternative would be to have your own command and control server running, python flask or similar, that then opens a local connection or runs a curl script. ...or may be use some secret key (or other similar authorisation way) for adding remote peer?

gh0st42 commented 7 months ago

This is not a bug but a (security) feature. got it, however (from working in i2p/tor overlay networks perspective) this is security feature will not work as your planed - because all incoming connections to opened hidden service will look (for this service) as local (in case if both started on one host).

you would then have to run two hidden services

The custom-dtnd-controller can then connect to 127.0.0.1:3000 (assuming its running on the same host as dtnd) and issue all commands as wanted. dtnd binds to 0.0.0.0 by default so a local process on the node can reach it not only through the hidden service address but also through a local IP.

This should solve your problem and has the added benefit that you can easily do other management stuff on the custom controller in between or easily add other authentication stuff.

gh0st42 commented 7 months ago

Another alternative would be to have your own command and control server running, python flask or similar, that then opens a local connection or runs a curl script. ...or may be use some secret key (or other similar authorisation way) for adding remote peer?

sure one could add something like basic authentication but this does not make sense in regular setups if you don't have transport layer security. thus, dtnd would need TLS support first, otherwise credentials can easily be compromised.

most people use either an SSH tunnel or VPN to manage remote dtnd nodes, or have a custom management protocol over DTN itself.

You could also just add a dtntrigger to react to your special messages and then reconfigure the node itself, e.g., via curl on localhost. BEWARE: BPsec support is not yet merged into upstream but coming "real soon[tm]". An alternative would be using openssl or GPG to secure your message content yourself.

iwojim0 commented 7 months ago

but this does not make sense in regular setups if you don't have transport layer security.

You absolutely right, for clearnet - sure, need to crypt transport level (TLS etc) But within tor/i2p networks (not in clearnet) transport level are secured by default and secret key for peering can be used more/less safety. I can try implement that for i2p/onion peers only - adding peering secret key to config and (if peer name is i2p/onion) requre use it, if adding/del initiated from remote... for all other clearnet cases all will stay as is - only local add/del. what you think?

gh0st42 commented 7 months ago

I don't want to have too much code in the main branch that is only for special cases but needs to be maintained and tested for all upcoming releases. That's also the reason we have the external CLA and routing interfaces so we don't have to add unmanagable amounts of code to the core :)

We wrote a LoRa overlay network called BPoL where we had similar requirements. Here we also used an external process to manage dtnd and its reconfiguration.

Reconfiguration and config updates via BP or an external transport such as HTTP(S) or LoRa with an external process are usually the cleanest and also most flexible solution as you can also rapidly prototype in a different language than rust. We're trying to follow the unix philosophy a bit in providing small building blocks that do one thing really well and can easily be combined with others for new features. That's why all the command line helpers also work really well with pipes and the whole rest interface can be used with trivial curl commands in scripts.

I'm not saying that authentication for the rest interface is never coming but since plenty of workarounds are there it is not a high priority and it needs some more thought on how to do it properly. This also needs new command line flags (there are already alot!) and config entries to activate password, etc.

gh0st42 commented 7 months ago

oh did you test your setup with the --unsafe-httpd flag? this should allow calls to all rest commands from anywhere not just localhost!

this can be dangerous but maybe this is what you want :)

gh0st42 commented 7 months ago

I'll close this issue for now but if you need further help feel free to open something in the discussion section, reopen this issue or join the matrix space for a chat :)