mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-01 06:17:56 +08:00
Merge pull request #1399 from ipfs/disable-secio-option
Swarm Addrs, Disable secio opt, + tests
This commit is contained in:
commit
2d6b787c99
@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -18,6 +19,7 @@ import (
|
||||
commands "github.com/ipfs/go-ipfs/core/commands"
|
||||
corehttp "github.com/ipfs/go-ipfs/core/corehttp"
|
||||
"github.com/ipfs/go-ipfs/core/corerouting"
|
||||
conn "github.com/ipfs/go-ipfs/p2p/net/conn"
|
||||
peer "github.com/ipfs/go-ipfs/p2p/peer"
|
||||
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
|
||||
util "github.com/ipfs/go-ipfs/util"
|
||||
@ -31,7 +33,8 @@ const (
|
||||
writableKwd = "writable"
|
||||
ipfsMountKwd = "mount-ipfs"
|
||||
ipnsMountKwd = "mount-ipns"
|
||||
unrestrictedApiAccess = "unrestricted-api"
|
||||
unrestrictedApiAccessKwd = "unrestricted-api"
|
||||
unencryptTransportKwd = "disable-transport-encryption"
|
||||
// apiAddrKwd = "address-api"
|
||||
// swarmAddrKwd = "address-swarm"
|
||||
)
|
||||
@ -75,7 +78,8 @@ the port as you would other services or database (firewall, authenticated proxy,
|
||||
cmds.BoolOption(writableKwd, "Enable writing objects (with POST, PUT and DELETE)"),
|
||||
cmds.StringOption(ipfsMountKwd, "Path to the mountpoint for IPFS (if using --mount)"),
|
||||
cmds.StringOption(ipnsMountKwd, "Path to the mountpoint for IPNS (if using --mount)"),
|
||||
cmds.BoolOption(unrestrictedApiAccess, "Allow API access to unlisted hashes"),
|
||||
cmds.BoolOption(unrestrictedApiAccessKwd, "Allow API access to unlisted hashes"),
|
||||
cmds.BoolOption(unencryptTransportKwd, "Disable transport encryption (for debugging protocols)"),
|
||||
|
||||
// TODO: add way to override addresses. tricky part: updating the config if also --init.
|
||||
// cmds.StringOption(apiAddrKwd, "Address for the daemon rpc API (overrides config)"),
|
||||
@ -109,6 +113,14 @@ func daemonFunc(req cmds.Request, res cmds.Response) {
|
||||
}
|
||||
}()
|
||||
|
||||
// check transport encryption flag.
|
||||
unencrypted, _, _ := req.Option(unencryptTransportKwd).Bool()
|
||||
if unencrypted {
|
||||
log.Warningf(`Running with --%s: All connections are UNENCRYPTED.
|
||||
You will not be able to connect to regular encrypted networks.`, unencryptTransportKwd)
|
||||
conn.EncryptConnections = false
|
||||
}
|
||||
|
||||
// first, whether user has provided the initialization flag. we may be
|
||||
// running in an uninitialized state.
|
||||
initialize, _, err := req.Option(initOptionKwd).Bool()
|
||||
@ -179,6 +191,8 @@ func daemonFunc(req cmds.Request, res cmds.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
printSwarmAddrs(node)
|
||||
|
||||
defer func() {
|
||||
// We wait for the node to close first, as the node has children
|
||||
// that it will wait for before closing, such as the API server.
|
||||
@ -256,9 +270,9 @@ func serveHTTPApi(req cmds.Request) (error, <-chan error) {
|
||||
apiMaddr = apiLis.Multiaddr()
|
||||
fmt.Printf("API server listening on %s\n", apiMaddr)
|
||||
|
||||
unrestricted, _, err := req.Option(unrestrictedApiAccess).Bool()
|
||||
unrestricted, _, err := req.Option(unrestrictedApiAccessKwd).Bool()
|
||||
if err != nil {
|
||||
return fmt.Errorf("serveHTTPApi: Option(%s) failed: %s", unrestrictedApiAccess, err), nil
|
||||
return fmt.Errorf("serveHTTPApi: Option(%s) failed: %s", unrestrictedApiAccessKwd, err), nil
|
||||
}
|
||||
|
||||
apiGw := corehttp.NewGateway(corehttp.GatewayConfig{
|
||||
@ -305,6 +319,19 @@ func serveHTTPApi(req cmds.Request) (error, <-chan error) {
|
||||
return nil, errc
|
||||
}
|
||||
|
||||
// printSwarmAddrs prints the addresses of the host
|
||||
func printSwarmAddrs(node *core.IpfsNode) {
|
||||
var addrs []string
|
||||
for _, addr := range node.PeerHost.Addrs() {
|
||||
addrs = append(addrs, addr.String())
|
||||
}
|
||||
sort.Sort(sort.StringSlice(addrs))
|
||||
|
||||
for _, addr := range addrs {
|
||||
fmt.Printf("Swarm listening on %s\n", addr)
|
||||
}
|
||||
}
|
||||
|
||||
// serveHTTPGateway collects options, creates listener, prints status message and starts serving requests
|
||||
func serveHTTPGateway(req cmds.Request) (error, <-chan error) {
|
||||
cfg, err := req.Context().GetConfig()
|
||||
|
||||
@ -46,6 +46,7 @@ ipfs id supports the format option for output with the following keys:
|
||||
<aver>: agent version
|
||||
<pver>: protocol version
|
||||
<pubkey>: public key
|
||||
<addrs>: addresses (newline delimited)
|
||||
`,
|
||||
},
|
||||
Arguments: []cmds.Argument{
|
||||
@ -119,6 +120,9 @@ ipfs id supports the format option for output with the following keys:
|
||||
output = strings.Replace(output, "<aver>", val.AgentVersion, -1)
|
||||
output = strings.Replace(output, "<pver>", val.ProtocolVersion, -1)
|
||||
output = strings.Replace(output, "<pubkey>", val.PublicKey, -1)
|
||||
output = strings.Replace(output, "<addrs>", strings.Join(val.Addresses, "\n"), -1)
|
||||
output = strings.Replace(output, "\\n", "\n", -1)
|
||||
output = strings.Replace(output, "\\t", "\t", -1)
|
||||
return strings.NewReader(output), nil
|
||||
} else {
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"sort"
|
||||
|
||||
cmds "github.com/ipfs/go-ipfs/commands"
|
||||
@ -91,6 +92,9 @@ var swarmAddrsCmd = &cmds.Command{
|
||||
ipfs swarm addrs lists all addresses this node is aware of.
|
||||
`,
|
||||
},
|
||||
Subcommands: map[string]*cmds.Command{
|
||||
"local": swarmAddrsLocalCmd,
|
||||
},
|
||||
Run: func(req cmds.Request, res cmds.Response) {
|
||||
|
||||
n, err := req.Context().GetNode()
|
||||
@ -144,6 +148,50 @@ ipfs swarm addrs lists all addresses this node is aware of.
|
||||
Type: addrMap{},
|
||||
}
|
||||
|
||||
var swarmAddrsLocalCmd = &cmds.Command{
|
||||
Helptext: cmds.HelpText{
|
||||
Tagline: "List local addresses.",
|
||||
ShortDescription: `
|
||||
ipfs swarm addrs local lists all local addresses the node is listening on.
|
||||
`,
|
||||
},
|
||||
Options: []cmds.Option{
|
||||
cmds.BoolOption("id", "Show peer ID in addresses"),
|
||||
},
|
||||
Run: func(req cmds.Request, res cmds.Response) {
|
||||
|
||||
n, err := req.Context().GetNode()
|
||||
if err != nil {
|
||||
res.SetError(err, cmds.ErrNormal)
|
||||
return
|
||||
}
|
||||
|
||||
if n.PeerHost == nil {
|
||||
res.SetError(errNotOnline, cmds.ErrClient)
|
||||
return
|
||||
}
|
||||
|
||||
showid, _, _ := req.Option("id").Bool()
|
||||
id := n.Identity.Pretty()
|
||||
|
||||
var addrs []string
|
||||
for _, addr := range n.PeerHost.Addrs() {
|
||||
saddr := addr.String()
|
||||
if showid {
|
||||
saddr = path.Join(saddr, "ipfs", id)
|
||||
}
|
||||
addrs = append(addrs, saddr)
|
||||
}
|
||||
sort.Sort(sort.StringSlice(addrs))
|
||||
|
||||
res.SetOutput(&stringList{addrs})
|
||||
},
|
||||
Type: stringList{},
|
||||
Marshalers: cmds.MarshalerMap{
|
||||
cmds.Text: stringListMarshaler,
|
||||
},
|
||||
}
|
||||
|
||||
var swarmConnectCmd = &cmds.Command{
|
||||
Helptext: cmds.HelpText{
|
||||
Tagline: "Open connection to a given address",
|
||||
|
||||
@ -60,7 +60,7 @@ func (d *Dialer) Dial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (
|
||||
return
|
||||
}
|
||||
|
||||
if d.PrivateKey == nil {
|
||||
if d.PrivateKey == nil || EncryptConnections == false {
|
||||
log.Warning("dialer %s dialing INSECURELY %s at %s!", d, remote, raddr)
|
||||
connOut = c
|
||||
return
|
||||
|
||||
@ -93,3 +93,11 @@ type Listener interface {
|
||||
// Any blocked Accept operations will be unblocked and return errors.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// EncryptConnections is a global parameter because it should either be
|
||||
// enabled or _completely disabled_. I.e. a node should only be able to talk
|
||||
// to proper (encrypted) networks if it is encrypting all its transports.
|
||||
// Running a node with disabled transport encryption is useful to debug the
|
||||
// protocols, achieve implementation interop, or for private networks which
|
||||
// -- for whatever reason -- _must_ run unencrypted.
|
||||
var EncryptConnections = true
|
||||
|
||||
@ -107,7 +107,7 @@ func (l *listener) Accept() (net.Conn, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if l.privk == nil {
|
||||
if l.privk == nil || EncryptConnections == false {
|
||||
log.Warning("listener %s listening INSECURELY!", l)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@ -43,24 +43,30 @@ func TestNotifications(t *testing.T) {
|
||||
for i, s := range nets {
|
||||
n := notifiees[i]
|
||||
for _, s2 := range nets {
|
||||
cos := s.ConnsToPeer(s2.LocalPeer())
|
||||
func() {
|
||||
for i := 0; i < len(cos); i++ {
|
||||
var c inet.Conn
|
||||
select {
|
||||
case c = <-n.connected:
|
||||
case <-time.After(timeout):
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
for _, c2 := range cos {
|
||||
if c == c2 {
|
||||
t.Log("got notif for conn")
|
||||
return
|
||||
}
|
||||
var actual []inet.Conn
|
||||
for len(s.ConnsToPeer(s2.LocalPeer())) != len(actual) {
|
||||
select {
|
||||
case c := <-n.connected:
|
||||
actual = append(actual, c)
|
||||
case <-time.After(timeout):
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
}
|
||||
|
||||
expect := s.ConnsToPeer(s2.LocalPeer())
|
||||
for _, c1 := range actual {
|
||||
found := false
|
||||
for _, c2 := range expect {
|
||||
if c1 == c2 {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Error("connection not found")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -11,8 +11,6 @@ import (
|
||||
)
|
||||
|
||||
func TestNotifications(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctx := context.Background()
|
||||
swarms := makeSwarms(ctx, t, 5)
|
||||
defer func() {
|
||||
@ -44,24 +42,30 @@ func TestNotifications(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
cos := s.ConnectionsToPeer(s2.LocalPeer())
|
||||
func() {
|
||||
for i := 0; i < len(cos); i++ {
|
||||
var c inet.Conn
|
||||
select {
|
||||
case c = <-n.connected:
|
||||
case <-time.After(timeout):
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
for _, c2 := range cos {
|
||||
if c == c2 {
|
||||
t.Log("got notif for conn", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Error("connection not found", c)
|
||||
var actual []inet.Conn
|
||||
for len(s.ConnectionsToPeer(s2.LocalPeer())) != len(actual) {
|
||||
select {
|
||||
case c := <-n.connected:
|
||||
actual = append(actual, c)
|
||||
case <-time.After(timeout):
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
expect := s.ConnectionsToPeer(s2.LocalPeer())
|
||||
for _, c1 := range actual {
|
||||
found := false
|
||||
for _, c2 := range expect {
|
||||
if c1 == c2 {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Error("connection not found")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -325,6 +325,6 @@ func TestFilterBounds(t *testing.T) {
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("should have gotten connection")
|
||||
case <-conns:
|
||||
fmt.Println("got connect")
|
||||
t.Log("got connect")
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,8 +193,10 @@ test_config_ipfs_gateway_writable() {
|
||||
|
||||
test_launch_ipfs_daemon() {
|
||||
|
||||
args=$1
|
||||
|
||||
test_expect_success "'ipfs daemon' succeeds" '
|
||||
ipfs daemon >actual_daemon 2>daemon_err &
|
||||
ipfs daemon $args >actual_daemon 2>daemon_err &
|
||||
'
|
||||
|
||||
# we say the daemon is ready when the API server is ready.
|
||||
|
||||
@ -8,6 +8,8 @@ test_description="Test daemon command"
|
||||
|
||||
. lib/test-lib.sh
|
||||
|
||||
# TODO: randomize ports here once we add --config to ipfs daemon
|
||||
|
||||
# this needs to be in a different test than "ipfs daemon --init" below
|
||||
test_expect_success "setup IPFS_PATH" '
|
||||
IPFS_PATH="$(pwd)/.ipfs" &&
|
||||
@ -17,7 +19,7 @@ test_expect_success "setup IPFS_PATH" '
|
||||
# NOTE: this should remove bootstrap peers (needs a flag)
|
||||
# TODO(cryptix):
|
||||
# - we won't see daemon startup failure because we put the daemon in the background - fix: fork with exit code after api listen
|
||||
# - also default ports: might clash with local clients. Failure in that case isn't clear as well because pollEndpoint just uses the already running node
|
||||
# - also default ports: might clash with local clients. Failure in that case isn't clear as well because pollEndpoint just uses the already running node
|
||||
test_expect_success "ipfs daemon --init launches" '
|
||||
ipfs daemon --init >actual_daemon 2>daemon_err &
|
||||
'
|
||||
@ -34,6 +36,11 @@ test_expect_success "'ipfs config Identity.PeerID' works" '
|
||||
ipfs config Identity.PeerID >config_peerId
|
||||
'
|
||||
|
||||
test_expect_success "'ipfs swarm addrs local' works" '
|
||||
ipfs swarm addrs local >local_addrs
|
||||
'
|
||||
|
||||
|
||||
# this is lifted straight from t0020-init.sh
|
||||
test_expect_success "ipfs peer id looks good" '
|
||||
PEERID=$(cat config_peerId) &&
|
||||
@ -58,6 +65,7 @@ test_expect_success "ipfs daemon output looks good" '
|
||||
echo "peer identity: $PEERID" >>expected_daemon &&
|
||||
echo "to get started, enter:" >>expected_daemon &&
|
||||
printf "\\n\\t$STARTFILE\\n\\n" >>expected_daemon &&
|
||||
cat local_addrs | sed "s/^/Swarm listening on /" >>expected_daemon &&
|
||||
echo "API server listening on /ip4/127.0.0.1/tcp/5001" >>expected_daemon &&
|
||||
echo "Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080" >>expected_daemon &&
|
||||
test_cmp expected_daemon actual_daemon
|
||||
@ -91,6 +99,15 @@ test_expect_success "ipfs help output looks good" '
|
||||
test_fsh cat help.txt
|
||||
'
|
||||
|
||||
# check transport is encrypted
|
||||
|
||||
test_expect_success 'transport should be encrypted' '
|
||||
nc -w 5 localhost 4001 >swarmnc &&
|
||||
grep -q "AES-256,AES-128" swarmnc &&
|
||||
test_must_fail grep -q "/ipfs/identify" swarmnc ||
|
||||
test_fsh cat swarmnc
|
||||
'
|
||||
|
||||
# end same as in t0010
|
||||
|
||||
test_expect_success "daemon is still running" '
|
||||
|
||||
38
test/sharness/t0061-daemon-opts.sh
Executable file
38
test/sharness/t0061-daemon-opts.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014 Juan Batiz-Benet
|
||||
# MIT Licensed; see the LICENSE file in this repository.
|
||||
#
|
||||
|
||||
test_description="Test daemon command"
|
||||
|
||||
. lib/test-lib.sh
|
||||
|
||||
|
||||
test_init_ipfs
|
||||
|
||||
test_launch_ipfs_daemon '--unrestricted-api --disable-transport-encryption'
|
||||
|
||||
gwyport=$PORT_GWAY
|
||||
apiport=$PORT_API
|
||||
|
||||
test_expect_success 'api gateway should be unrestricted' '
|
||||
echo "hello mars :$gwyport :$apiport" >expected &&
|
||||
HASH=$(ipfs add -q expected) &&
|
||||
curl -sfo actual1 "http://127.0.0.1:$gwyport/ipfs/$HASH" &&
|
||||
curl -sfo actual2 "http://127.0.0.1:$apiport/ipfs/$HASH" &&
|
||||
test_cmp expected actual1 &&
|
||||
test_cmp expected actual2
|
||||
'
|
||||
|
||||
# Odd. this fails here, but the inverse works on t0060-daemon.
|
||||
test_expect_success 'transport should be unencrypted' '
|
||||
go-sleep 0.5s | nc localhost "$PORT_SWARM" >swarmnc &&
|
||||
test_must_fail grep -q "AES-256,AES-128" swarmnc &&
|
||||
grep -q "/ipfs/identify" swarmnc ||
|
||||
test_fsh cat swarmnc
|
||||
'
|
||||
|
||||
test_kill_ipfs_daemon
|
||||
|
||||
test_done
|
||||
@ -33,6 +33,10 @@ test_expect_success "GET IPFS path output looks good" '
|
||||
rm actual
|
||||
'
|
||||
|
||||
test_expect_success "GET IPFS path on API forbidden" '
|
||||
test_curl_resp_http_code "http://127.0.0.1:$apiport/ipfs/$HASH" "HTTP/1.1 403 Forbidden"
|
||||
'
|
||||
|
||||
test_expect_success "GET IPFS directory path succeeds" '
|
||||
mkdir dir &&
|
||||
echo "12345" >dir/test &&
|
||||
|
||||
33
test/sharness/t0140-swarm.sh
Executable file
33
test/sharness/t0140-swarm.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014 Jeromy Johnson
|
||||
# MIT Licensed; see the LICENSE file in this repository.
|
||||
#
|
||||
|
||||
test_description="Test ipfs swarm command"
|
||||
|
||||
. lib/test-lib.sh
|
||||
|
||||
test_init_ipfs
|
||||
|
||||
test_launch_ipfs_daemon
|
||||
|
||||
test_expect_success 'disconnected: peers is empty' '
|
||||
ipfs swarm peers >actual &&
|
||||
test_must_be_empty actual
|
||||
'
|
||||
|
||||
test_expect_success 'disconnected: addrs local has localhost' '
|
||||
ipfs swarm addrs local >actual &&
|
||||
grep "/ip4/127.0.0.1" actual
|
||||
'
|
||||
|
||||
test_expect_success 'disconnected: addrs local matches ipfs id' '
|
||||
ipfs id -f="<addrs>\\n" | sort >expected &&
|
||||
ipfs swarm addrs local --id | sort >actual &&
|
||||
test_cmp expected actual
|
||||
'
|
||||
|
||||
test_kill_ipfs_daemon
|
||||
|
||||
test_done
|
||||
Loading…
Reference in New Issue
Block a user