Browse Source

Merge 43b869a50d into 16c6af5d90

pull/215/merge
Timoshenko 8 months ago committed by GitHub
parent
commit
d430296e7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. BIN
      .gck.sh.swp
  2. 27
      auth/entity/client/client.go
  3. 43
      auth/entity/session/session.go
  4. 141
      auth/security.go
  5. 22
      auth/utils/utils.go
  6. 8
      configure/liveconfig.go
  7. 12
      gck.sh
  8. 3
      livego.yaml
  9. 1
      protocol/rtmp/core/conn_server.go
  10. 16
      protocol/rtmp/rtmp.go

BIN
.gck.sh.swp

Binary file not shown.

27
auth/entity/client/client.go

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
package client
import "encoding/json"
type Client struct {
Email string `json:"email,omitempty"`
Code string `json:"code,omitempty"`
Key string `json:"key,omitempty"`
Active bool `json:"active,omitempty"`
LastSessionKey string `json:"lsk,omitempty"`
}
type Clients = []Client
func New() *Client {
return &Client{}
}
func (client *Client) ToJson() ([]byte, error) {
return json.Marshal(client)
}
func FromJson(data []byte) (client *Client, err error) {
client = New()
err = json.Unmarshal(data, client)
return
}

43
auth/entity/session/session.go

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
package connection
import (
"encoding/json"
"fmt"
"time"
"github.com/gwuhaolin/livego/auth/utils"
)
type Session struct {
_Key string
TimeStamp string `json:"time,omitempty"`
Code string `json:"code,omitempty"`
IpAddress string `json:"ip,omitempty"`
Active bool `json:"active,omitempty"`
}
type Connections = []Session
func New(code, IpAddress string) *Session {
return &Session{
_Key: fmt.Sprintf("session-[%s-%s]", utils.RandomNumberString(4), utils.RandomNumberString(5)),
TimeStamp: time.Now().UTC().Format(time.RFC3339Nano),
Code: code,
IpAddress: IpAddress,
Active: true,
}
}
func (session *Session) Key() string {
return session._Key
}
func (client *Session) ToJson() ([]byte, error) {
return json.Marshal(client)
}
func FromJson(data []byte) (conn *Session, err error) {
conn = &Session{}
err = json.Unmarshal(data, conn)
return
}

141
auth/security.go

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
package auth
import (
"fmt"
"net/url"
"strings"
"github.com/go-redis/redis/v7"
log "github.com/sirupsen/logrus"
cli "github.com/gwuhaolin/livego/auth/entity/client"
sess "github.com/gwuhaolin/livego/auth/entity/session"
"github.com/gwuhaolin/livego/configure"
)
var Auth *Security
type Security struct {
redisCli *redis.Client
Allow func(string, string) (bool, error)
}
func init() {
protected := configure.Config.GetBool("is_protected")
log.Infof("security.init(): %v", protected)
// Identify if Authentication is enabled:
Auth = New(protected)
// =====================================================
log.Infof("redis_addr: %s | redis_pwd: %s | redis_db: %d",
configure.Config.GetString("redis_addr"),
configure.Config.GetString("redis_pwd"),
configure.Config.GetInt("redis_db"))
if len(configure.Config.GetString("redis_addr")) != 0 {
Auth.redisCli = redis.NewClient(&redis.Options{
Addr: configure.Config.GetString("redis_addr"),
Password: configure.Config.GetString("redis_pwd"),
DB: configure.Config.GetInt("redis_db"),
})
_, err := Auth.redisCli.Ping().Result()
if err != nil {
log.Panic("Redis: ", err)
}
log.Info("Redis connected")
}
}
func New(protected bool) (security *Security) {
security = &Security{}
if protected {
security.Allow = security.allow
} else {
security.Allow = func(string, string) (bool, error) {
log.Debugf("security.Allow(): default true")
return true, nil // Default true
}
}
return
}
func (security *Security) allow(ipAddr, value string) (allowed bool, err error) {
allowed = false
if url, err := url.Parse(value); err == nil {
user := url.Query().Get("u")
key := url.Query().Get("k")
log.Debugf("security.Allow(): [%s]-[%s]", user, len(key) > 0)
if client, err := security.findClient(user); err == nil {
if client != nil && client.Active {
lsk := client.LastSessionKey
session, err := security.findSession(lsk)
if err == redis.Nil || session == nil {
session = sess.New(user, ipAddr)
if err = security.saveSession(session); err == nil {
client.LastSessionKey = session.Key()
if err = security.saveClient(client); err == nil {
log.Debugf("security.Allow(): %+v", session)
allowed = true
}
}
} else {
// Validate the IP Address from source to identify if it is another session to the same user:
allowed = (strings.Split(ipAddr, ":")[0] == strings.Split(session.IpAddress, ":")[0])
}
}
}
}
if err != nil {
log.Errorf("security.Allow(): %s", err.Error())
}
return
}
func (s *Security) findClient(code string) (*cli.Client, error) {
if value, err := s.redisCli.Get(fmt.Sprintf("client-%s", code)).Result(); err == nil {
return cli.FromJson([]byte(value))
} else {
return nil, err
}
}
func (s *Security) saveClient(client *cli.Client) (err error) {
content, _ := client.ToJson()
cmd_val, err := s.redisCli.Set(fmt.Sprintf("client-%s", client.Code), string(content), 0).Result()
log.Debugf("security.saveClient(): %s", cmd_val)
return
}
func (s *Security) findSession(key string) (*sess.Session, error) {
if value, err := s.redisCli.Get(key).Result(); err == nil {
return sess.FromJson([]byte(value))
} else {
return nil, err
}
}
func (s *Security) saveSession(session *sess.Session) (err error) {
content, _ := session.ToJson()
cmd_val, err := s.redisCli.Set(session.Key(), string(content), 0).Result()
log.Debugf("security.saveSession(): %s", cmd_val)
return
}

22
auth/utils/utils.go

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package utils
import (
"math/rand"
"strconv"
"strings"
"time"
)
func init() {
rand.Seed(time.Now().Unix())
}
func RandomNumberString(length int) string {
var result strings.Builder
for n := 0; n < length; n++ {
result.WriteString(strconv.Itoa(rand.Intn(9)))
}
return result.String()
}

8
configure/liveconfig.go

@ -41,6 +41,7 @@ type JWT struct { @@ -41,6 +41,7 @@ type JWT struct {
}
type ServerCfg struct {
Level string `mapstructure:"level"`
IsProtected bool `mapstructure:"is_protected"`
ConfigFile string `mapstructure:"config_file"`
FLVArchive bool `mapstructure:"flv_archive"`
FLVDir string `mapstructure:"flv_dir"`
@ -52,6 +53,7 @@ type ServerCfg struct { @@ -52,6 +53,7 @@ type ServerCfg struct {
APIAddr string `mapstructure:"api_addr"`
RedisAddr string `mapstructure:"redis_addr"`
RedisPwd string `mapstructure:"redis_pwd"`
RedisDb int `mapstructure:"redis_db"`
ReadTimeout int `mapstructure:"read_timeout"`
WriteTimeout int `mapstructure:"write_timeout"`
EnableTLSVerify bool `mapstructure:"enable_tls_verify"`
@ -187,3 +189,9 @@ func GetStaticPushUrlList(appname string) ([]string, bool) { @@ -187,3 +189,9 @@ func GetStaticPushUrlList(appname string) ([]string, bool) {
}
return nil, false
}
func IsProtected() bool {
c := ServerCfg{}
Config.Unmarshal(&c)
return c.IsProtected
}

12
gck.sh

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#/bin/bash
if [ $# -ne 1 ]
then
CHANNEL="${RANDOM}-${RANDOM}-${RANDOM}"
else
CHANNEL="${1}"
fi
echo ${CHANNEL}
curl "http://localhost:8090/control/get?room=${CHANNEL}"
echo

3
livego.yaml

@ -21,6 +21,9 @@ @@ -21,6 +21,9 @@
# # API Options
# api_addr: ":8090"
is_protected: true
redis_addr: "localhost:6379"
# redis_db: 10
server:
- appname: live
live: true

1
protocol/rtmp/core/conn_server.go

@ -350,6 +350,7 @@ func (connServer *ConnServer) GetInfo() (app string, name string, url string) { @@ -350,6 +350,7 @@ func (connServer *ConnServer) GetInfo() (app string, name string, url string) {
app = connServer.ConnInfo.App
name = connServer.PublishInfo.Name
url = connServer.ConnInfo.TcUrl + "/" + connServer.PublishInfo.Name
log.Debugf("connServer.GetInfo: [%s]-[%s]-[%s]", app, name, url)
return
}

16
protocol/rtmp/rtmp.go

@ -10,6 +10,7 @@ import ( @@ -10,6 +10,7 @@ import (
"github.com/gwuhaolin/livego/utils/uid"
"github.com/gwuhaolin/livego/auth"
"github.com/gwuhaolin/livego/av"
"github.com/gwuhaolin/livego/configure"
"github.com/gwuhaolin/livego/container/flv"
@ -91,8 +92,8 @@ func (s *Server) Serve(listener net.Listener) (err error) { @@ -91,8 +92,8 @@ func (s *Server) Serve(listener net.Listener) (err error) {
return
}
conn := core.NewConn(netconn, 4*1024)
log.Debug("new client, connect remote: ", conn.RemoteAddr().String(),
"local:", conn.LocalAddr().String())
log.Debugf("new client, connect remote: %s local: %s", conn.RemoteAddr().String(),
conn.LocalAddr().String())
go s.handleConn(conn)
}
}
@ -111,7 +112,16 @@ func (s *Server) handleConn(conn *core.Conn) error { @@ -111,7 +112,16 @@ func (s *Server) handleConn(conn *core.Conn) error {
return err
}
appname, name, _ := connServer.GetInfo()
appname, name, uri := connServer.GetInfo()
// If is not a publisher we need to validate the credential here......
if !connServer.IsPublisher() && configure.IsProtected() {
if allow, err := auth.Auth.Allow(conn.RemoteAddr().String(), uri); err != nil || !allow {
conn.Close()
log.Error("handleConn auth err: ", allow, err)
return err
}
}
if ret := configure.CheckAppName(appname); !ret {
err := fmt.Errorf("application name=%s is not configured", appname)

Loading…
Cancel
Save