diff --git a/common/buf/multi_buffer.go b/common/buf/multi_buffer.go
index 82f1f030..f7422808 100644
--- a/common/buf/multi_buffer.go
+++ b/common/buf/multi_buffer.go
@@ -1,6 +1,11 @@
 package buf
 
-import "net"
+import (
+	"io"
+	"net"
+
+	"v2ray.com/core/common/errors"
+)
 
 type MultiBufferWriter interface {
 	WriteMultiBuffer(MultiBuffer) error
@@ -10,6 +15,36 @@ type MultiBufferReader interface {
 	ReadMultiBuffer() (MultiBuffer, error)
 }
 
+func ReadAllToMultiBuffer(reader io.Reader) (MultiBuffer, error) {
+	mb := NewMultiBuffer()
+
+	for {
+		b := New()
+		err := b.AppendSupplier(ReadFrom(reader))
+		if !b.IsEmpty() {
+			mb.Append(b)
+		}
+		if err != nil {
+			if errors.Cause(err) == io.EOF {
+				return mb, nil
+			}
+			mb.Release()
+			return nil, err
+		}
+	}
+}
+
+func ReadAllToBytes(reader io.Reader) ([]byte, error) {
+	mb, err := ReadAllToMultiBuffer(reader)
+	if err != nil {
+		return nil, err
+	}
+	b := make([]byte, mb.Len())
+	mb.Read(b)
+	mb.Release()
+	return b, nil
+}
+
 // MultiBuffer is a list of Buffers. The order of Buffer matters.
 type MultiBuffer []*Buffer
 
diff --git a/loader.go b/loader.go
index 07ef279c..40ebb6fc 100644
--- a/loader.go
+++ b/loader.go
@@ -2,10 +2,11 @@ package core
 
 import (
 	"io"
-	"io/ioutil"
+
+	"v2ray.com/core/common"
+	"v2ray.com/core/common/buf"
 
 	"github.com/golang/protobuf/proto"
-	"v2ray.com/core/common"
 )
 
 // ConfigLoader is an utility to load V2Ray config from external source.
@@ -30,7 +31,10 @@ func LoadConfig(format ConfigFormat, input io.Reader) (*Config, error) {
 
 func loadProtobufConfig(input io.Reader) (*Config, error) {
 	config := new(Config)
-	data, _ := ioutil.ReadAll(input)
+	data, err := buf.ReadAllToBytes(input)
+	if err != nil {
+		return nil, err
+	}
 	if err := proto.Unmarshal(data, config); err != nil {
 		return nil, err
 	}