Allow binding HTTP server to specific address (#831)

Improves security when running with placeholder keys. Only allowing
access from loopback by default.
This commit is contained in:
David Zhao
2022-07-13 23:58:33 -07:00
committed by GitHub
parent af93954c26
commit a2bf32797b
5 changed files with 78 additions and 40 deletions
+16 -4
View File
@@ -32,6 +32,10 @@ func main() {
Usage: "High performance WebRTC server",
Description: "run without subcommands to start the server",
Flags: []cli.Flag{
&cli.StringSliceFlag{
Name: "bind",
Usage: "IP address to listen on, use flag multiple times to specify multiple addresses",
},
&cli.StringFlag{
Name: "config",
Usage: "path to LiveKit config file",
@@ -92,7 +96,7 @@ func main() {
},
&cli.BoolFlag{
Name: "dev",
Usage: "sets log-level to debug, console formatter, and /debug/pprof. insecure for production.",
Usage: "sets log-level to debug, console formatter, and /debug/pprof. insecure for production",
},
},
Action: startServer,
@@ -108,7 +112,9 @@ func main() {
Action: printPorts,
},
{
// this subcommand is deprecated, token generation is provided by CLI
Name: "create-join-token",
Hidden: true,
Usage: "create a room join token for development use",
Action: createToken,
Flags: []cli.Flag{
@@ -155,9 +161,8 @@ func getConfig(c *cli.Context) (*config.Config, error) {
}
serverlogger.InitFromConfig(conf.Logging)
if c.String("config") == "" && c.String("config-body") == "" {
// without config, use single port UDP
conf.Development = true
if c.String("config") == "" && c.String("config-body") == "" && conf.Development {
// use single port UDP when no config is provided
conf.RTC.UDPPort = 7882
conf.RTC.ICEPortRangeStart = 0
conf.RTC.ICEPortRangeEnd = 0
@@ -171,6 +176,13 @@ func getConfig(c *cli.Context) (*config.Config, error) {
conf.Keys = map[string]string{
"devkey": "secret",
}
// when dev mode and using shared keys, we'll bind to localhost by default
if conf.BindAddresses == nil {
conf.BindAddresses = []string{
"127.0.0.1",
"[::1]",
}
}
}
}
return conf, nil
+1
View File
@@ -42,6 +42,7 @@ require (
github.com/urfave/negroni v1.0.0
go.uber.org/atomic v1.9.0
go.uber.org/zap v1.21.0
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0
)
+1
View File
@@ -347,6 +347,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+4 -1
View File
@@ -30,6 +30,7 @@ const (
type Config struct {
Port uint32 `yaml:"port"`
BindAddresses []string `yaml:"bind_addresses"`
PrometheusPort uint32 `yaml:"prometheus_port,omitempty"`
RTC RTCConfig `yaml:"rtc,omitempty"`
Redis RedisConfig `yaml:"redis,omitempty"`
@@ -347,7 +348,9 @@ func (conf *Config) updateFromCLI(c *cli.Context) error {
if c.IsSet("udp-port") {
conf.RTC.UDPPort = uint32(c.Int("udp-port"))
}
if c.IsSet("bind") {
conf.BindAddresses = c.StringSlice("bind")
}
return nil
}
+56 -35
View File
@@ -16,6 +16,7 @@ import (
"github.com/rs/cors"
"github.com/urfave/negroni"
"go.uber.org/atomic"
"golang.org/x/sync/errgroup"
"github.com/livekit/livekit-server/pkg/config"
"github.com/livekit/livekit-server/pkg/routing"
@@ -94,13 +95,11 @@ func NewLivekitServer(conf *config.Config,
mux.HandleFunc("/", s.healthCheck)
s.httpServer = &http.Server{
Addr: fmt.Sprintf(":%d", conf.Port),
Handler: configureMiddlewares(mux, middlewares...),
}
if conf.PrometheusPort > 0 {
s.promServer = &http.Server{
Addr: fmt.Sprintf(":%d", conf.PrometheusPort),
Handler: promhttp.Handler(),
}
}
@@ -149,47 +148,69 @@ func (s *LivekitServer) Start() error {
s.egressService.Start()
// ensure we could listen
ln, err := net.Listen("tcp", s.httpServer.Addr)
if err != nil {
return err
addresses := s.config.BindAddresses
if addresses == nil {
addresses = []string{""}
}
if s.promServer != nil {
promLn, err := net.Listen("tcp", s.promServer.Addr)
// ensure we could listen
listeners := make([]net.Listener, 0)
promListeners := make([]net.Listener, 0)
for _, addr := range addresses {
ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, s.config.Port))
if err != nil {
return err
}
go func() {
_ = s.promServer.Serve(promLn)
}()
listeners = append(listeners, ln)
if s.promServer != nil {
ln, err = net.Listen("tcp", fmt.Sprintf("%s:%d", addr, s.config.PrometheusPort))
if err != nil {
return err
}
promListeners = append(promListeners, ln)
}
}
values := []interface{}{
"portHttp", s.config.Port,
"nodeID", s.currentNode.Id,
"nodeIP", s.currentNode.Ip,
"version", version.Version,
}
if s.config.BindAddresses != nil {
values = append(values, "bindAddresses", s.config.BindAddresses)
}
if s.config.RTC.TCPPort != 0 {
values = append(values, "rtc.portTCP", s.config.RTC.TCPPort)
}
if !s.config.RTC.ForceTCP && s.config.RTC.UDPPort != 0 {
values = append(values, "rtc.portUDP", s.config.RTC.UDPPort)
} else {
values = append(values,
"rtc.portICERange", []uint32{s.config.RTC.ICEPortRangeStart, s.config.RTC.ICEPortRangeEnd},
)
}
if s.config.PrometheusPort != 0 {
values = append(values, "portPrometheus", s.config.PrometheusPort)
}
if s.config.Region != "" {
values = append(values, "region", s.config.Region)
}
logger.Infow("starting LiveKit server", values...)
for _, promLn := range promListeners {
go s.promServer.Serve(promLn)
}
httpGroup := &errgroup.Group{}
for _, ln := range listeners {
httpGroup.Go(func() error {
return s.httpServer.Serve(ln)
})
}
go func() {
values := []interface{}{
"addr", s.httpServer.Addr,
"nodeID", s.currentNode.Id,
"nodeIP", s.currentNode.Ip,
"version", version.Version,
}
if s.config.RTC.TCPPort != 0 {
values = append(values, "rtc.portTCP", s.config.RTC.TCPPort)
}
if !s.config.RTC.ForceTCP && s.config.RTC.UDPPort != 0 {
values = append(values, "rtc.portUDP", s.config.RTC.UDPPort)
} else {
values = append(values,
"rtc.portICERange", []uint32{s.config.RTC.ICEPortRangeStart, s.config.RTC.ICEPortRangeEnd},
)
}
if s.config.PrometheusPort != 0 {
values = append(values, "portPrometheus", s.config.PrometheusPort)
}
if s.config.Region != "" {
values = append(values, "region", s.config.Region)
}
logger.Infow("starting LiveKit server", values...)
if err := s.httpServer.Serve(ln); err != http.ErrServerClosed {
if err := httpGroup.Wait(); err != http.ErrServerClosed {
logger.Errorw("could not start server", err)
s.Stop(true)
}