github.com/metaworking/channeld@v0.7.3/pkg/channeld/ddos_test.go (about)

     1  package channeld
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"os"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/metaworking/channeld/pkg/channeldpb"
    11  	"github.com/stretchr/testify/assert"
    12  	"google.golang.org/protobuf/proto"
    13  )
    14  
    15  func TestUnauthTimeout(t *testing.T) {
    16  	InitLogs()
    17  	InitAntiDDoS()
    18  	// InitChannels()
    19  	InitConnections("../../config/server_conn_fsm_test.json", "../../config/client_non_authoratative_fsm.json")
    20  
    21  	GlobalSettings.ConnectionAuthTimeoutMs = 1000
    22  
    23  	// go StartListening(channeldpb.ConnectionType_SERVER, "tcp", ":31288")
    24  	go StartListening(channeldpb.ConnectionType_CLIENT, "tcp", ":32108")
    25  	time.Sleep(time.Millisecond * 100)
    26  
    27  	conn, err := net.Dial("tcp", "127.0.0.1:32108")
    28  	assert.NoError(t, err, "Error connecting to server")
    29  
    30  	assert.True(t, checkConnOpen(conn), "Connection should not have been closed yet")
    31  
    32  	time.Sleep(time.Millisecond * time.Duration(GlobalSettings.ConnectionAuthTimeoutMs))
    33  	assert.True(t, checkConnClosed(conn), "Connection should have been closed by now")
    34  
    35  	// IP blacklisted. Should still be able to connect, but will be soon be disconnected
    36  	conn, _ = net.Dial("tcp", "127.0.0.1:32108")
    37  	time.Sleep(time.Millisecond * 100)
    38  	assert.True(t, checkConnClosed(conn), "Connection should have been closed by now")
    39  }
    40  
    41  func TestInvalidUsername(t *testing.T) {
    42  	InitLogs()
    43  	InitAntiDDoS()
    44  	InitChannels()
    45  	InitConnections("../../config/server_conn_fsm_test.json", "../../config/client_non_authoratative_fsm.json")
    46  
    47  	// Turn off dev mode to force authentication
    48  	GlobalSettings.Development = false
    49  	GlobalSettings.MaxFailedAuthAttempts = 2
    50  	SetAuthProvider(&AlwaysFailAuthProvider{})
    51  
    52  	go StartListening(channeldpb.ConnectionType_CLIENT, "tcp", ":32108")
    53  	time.Sleep(time.Millisecond * 100)
    54  
    55  	conn, err := net.Dial("tcp", "127.0.0.1:32108")
    56  	assert.NoError(t, err, "Error connecting to server")
    57  
    58  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
    59  		PlayerIdentifierToken: "user1",
    60  	})
    61  	time.Sleep(time.Millisecond * 100)
    62  	assert.Contains(t, failedAuthCounters, "127.0.0.1", "Failed auth counter should contain 127.0.0.1")
    63  	assert.True(t, checkConnOpen(conn), "Connection should not have been closed yet")
    64  
    65  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
    66  		PlayerIdentifierToken: "user2",
    67  	})
    68  	time.Sleep(time.Millisecond * 200)
    69  	assert.EqualValues(t, 2, failedAuthCounters["127.0.0.1"], "Failed auth counter should be 2")
    70  	// Read all bytes to clear the read buffer, so checkConnOpen/Closed can work
    71  	readAll(conn)
    72  	assert.False(t, checkConnOpen(conn), "Connection should have been closed now")
    73  	/*
    74  		_, err = conn.Write([]byte{0, 0, 0, 0})
    75  		assert.Error(t, err, "Connection should have been closed now")
    76  	*/
    77  
    78  	// IP blacklisted. Should still be able to connect, but will be soon be disconnected
    79  	conn, _ = net.Dial("tcp", "127.0.0.1:32108")
    80  	time.Sleep(time.Millisecond * 100)
    81  	assert.True(t, checkConnClosed(conn), "Connection should have been closed now")
    82  }
    83  
    84  func TestWrongPassword(t *testing.T) {
    85  	InitLogs()
    86  	InitAntiDDoS()
    87  	InitChannels()
    88  	InitConnections("../../config/server_conn_fsm_test.json", "../../config/client_non_authoratative_fsm.json")
    89  
    90  	// Turn off dev mode to force authentication
    91  	GlobalSettings.Development = false
    92  	GlobalSettings.MaxFailedAuthAttempts = 3
    93  	SetAuthProvider(&FixedPasswordAuthProvider{"rightpassword"})
    94  
    95  	go StartListening(channeldpb.ConnectionType_CLIENT, "tcp", ":32108")
    96  	time.Sleep(time.Millisecond * 100)
    97  
    98  	conn, err := net.Dial("tcp", "127.0.0.1:32108")
    99  	assert.NoError(t, err, "Error connecting to server")
   100  
   101  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
   102  		PlayerIdentifierToken: "user1",
   103  		LoginToken:            "wrongpassword",
   104  	})
   105  	time.Sleep(time.Millisecond * 100)
   106  	assert.Contains(t, failedAuthCounters, "user1", "Failed auth counter should contain user1")
   107  	assert.True(t, checkConnOpen(conn), "Connection should not have been closed yet")
   108  
   109  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
   110  		PlayerIdentifierToken: "user1",
   111  		LoginToken:            "wrongpassword",
   112  	})
   113  	time.Sleep(time.Millisecond * 100)
   114  	assert.EqualValues(t, 2, failedAuthCounters["user1"], "Failed auth counter should be 2")
   115  	assert.True(t, checkConnOpen(conn), "Connection should not have been closed yet")
   116  
   117  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
   118  		PlayerIdentifierToken: "user1",
   119  		LoginToken:            "rightpassword",
   120  	})
   121  	time.Sleep(time.Millisecond * 100)
   122  	assert.EqualValues(t, 2, failedAuthCounters["user1"], "Failed auth counter should still be 2")
   123  	assert.True(t, checkConnOpen(conn), "Connection should not have been closed yet")
   124  
   125  	conn.Close()
   126  	time.Sleep(time.Millisecond * 100)
   127  	// Re-open connection as the FSM only allows valid AuthMessage once
   128  	conn, err = net.Dial("tcp", "127.0.0.1:32108")
   129  	assert.NoError(t, err, "Error connecting to server")
   130  
   131  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
   132  		PlayerIdentifierToken: "user1",
   133  		LoginToken:            "wrongpassword",
   134  	})
   135  	time.Sleep(time.Millisecond * 100)
   136  	assert.False(t, checkConnOpen(conn), "Connection should have been closed by now")
   137  
   138  	// PIT blacklisted. Should still be able to connect, but can't login anymore
   139  	conn, _ = net.Dial("tcp", "127.0.0.1:32108")
   140  	time.Sleep(time.Millisecond * 100)
   141  	assert.True(t, checkConnOpen(conn), "Connection should have been closed by now")
   142  	sendMessage(conn, uint32(channeldpb.MessageType_AUTH), &channeldpb.AuthMessage{
   143  		PlayerIdentifierToken: "user1",
   144  		LoginToken:            "rightpassword",
   145  	})
   146  	time.Sleep(time.Millisecond * 100)
   147  	// Event the right password won't work anymore
   148  	assert.False(t, checkConnOpen(conn), "Connection should have been closed by now")
   149  }
   150  
   151  func sendMessage(conn net.Conn, msgType uint32, msg proto.Message) {
   152  	msgBody, _ := proto.Marshal(msg)
   153  	p := &channeldpb.Packet{
   154  		Messages: []*channeldpb.MessagePack{
   155  			{
   156  				MsgType: msgType,
   157  				MsgBody: msgBody,
   158  			},
   159  		},
   160  	}
   161  	bytes, _ := proto.Marshal(p)
   162  	tag := []byte{67, 72, 78, byte(len(bytes)), 0}
   163  	conn.Write(append(tag, bytes...))
   164  }
   165  
   166  func readAll(conn net.Conn) []byte {
   167  	buff := make([]byte, 1024)
   168  	conn.SetReadDeadline(time.Now().Add(time.Millisecond * 50))
   169  	n, _ := conn.Read(buff)
   170  	return buff[:n]
   171  }
   172  
   173  func checkConnOpen(conn net.Conn) bool {
   174  	buff := make([]byte, 1)
   175  	conn.SetReadDeadline(time.Now().Add(time.Millisecond * 50))
   176  	_, err := conn.Read(buff)
   177  	if err != nil {
   178  		return errors.Is(err, os.ErrDeadlineExceeded)
   179  	}
   180  	return true
   181  }
   182  
   183  func checkConnClosed(conn net.Conn) bool {
   184  	buff := make([]byte, 1)
   185  	conn.SetReadDeadline(time.Time{})
   186  	_, err := conn.Read(buff)
   187  	return err != nil
   188  }