inbound_finalmask_salamander_test.go 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package service
  2. import (
  3. "strings"
  4. "testing"
  5. "github.com/mhsanaei/3x-ui/v3/internal/database/model"
  6. "github.com/mhsanaei/3x-ui/v3/internal/web/entity"
  7. )
  8. func hysteriaSalamanderStream(password string) string {
  9. return `{"network":"hysteria","security":"tls","hysteriaSettings":{"version":2},
  10. "tlsSettings":{"alpn":["h3"],"certificates":[{"certificateFile":"/etc/ssl/h.crt","keyFile":"/etc/ssl/h.key"}]},
  11. "finalmask":{"udp":[{"type":"salamander","settings":{"password":"` + password + `"}}]}}`
  12. }
  13. func hysteriaInbound(port int, stream string) *model.Inbound {
  14. return &model.Inbound{
  15. Enable: true, Listen: "127.0.0.1", Port: port, Protocol: model.Hysteria,
  16. Settings: `{"version":2,"clients":[{"email":"[email protected]","auth":"a","enable":true}]}`,
  17. StreamSettings: stream,
  18. }
  19. }
  20. // xray-core loads a salamander mask whose password is under 4 bytes and refuses it only when the
  21. // socket opens: on an inbound that stops every listener, so each save path must refuse it.
  22. func TestSavePathsRefuseShortSalamanderPassword(t *testing.T) {
  23. const want = "salamander finalmask password must be at least 4 bytes"
  24. tests := []struct {
  25. name string
  26. save func(t *testing.T) error
  27. }{
  28. {"add inbound", func(t *testing.T) error {
  29. _, _, err := (&InboundService{}).AddInbound(hysteriaInbound(18443, hysteriaSalamanderStream("")))
  30. return err
  31. }},
  32. {"update inbound", func(t *testing.T) error {
  33. in, _, err := (&InboundService{}).AddInbound(hysteriaInbound(18444, hysteriaSalamanderStream("long-enough")))
  34. if err != nil {
  35. t.Fatalf("AddInbound: %v", err)
  36. }
  37. in.StreamSettings = hysteriaSalamanderStream("abc")
  38. _, _, err = (&InboundService{}).UpdateInbound(in)
  39. return err
  40. }},
  41. {"add host", func(t *testing.T) error {
  42. ib := mkInbound(t, 18445, model.VLESS, `{"clients":[]}`)
  43. _, err := (&HostService{}).AddHostGroup(&entity.HostGroup{
  44. InboundIds: []int{ib.Id}, Remark: "h", Port: 443,
  45. FinalMask: `{"udp":[{"type":"salamander","settings":{"password":"€"}}]}`,
  46. })
  47. return err
  48. }},
  49. {"subscription JSON finalmask", func(t *testing.T) error {
  50. s := &SettingService{}
  51. all, err := s.GetAllSetting()
  52. if err != nil {
  53. t.Fatalf("GetAllSetting: %v", err)
  54. }
  55. all.SubJsonFinalMask = `{"udp":[{"type":"salamander","settings":{"password":"ab"}}]}`
  56. return s.UpdateAllSetting(all, SecretClears{})
  57. }},
  58. {"xray template inbound", func(t *testing.T) error {
  59. return (&XraySettingService{}).SaveXraySetting(`{"inbounds":[{"tag":"hy","port":18446,"protocol":"hysteria",
  60. "settings":{"version":2,"clients":[]},"streamSettings":` + hysteriaSalamanderStream("") + `}],
  61. "outbounds":[{"protocol":"freedom","tag":"direct"}]}`)
  62. }},
  63. {"xray template outbound", func(t *testing.T) error {
  64. return (&XraySettingService{}).SaveXraySetting(`{"outbounds":[{"protocol":"freedom","tag":"direct"},
  65. {"protocol":"hysteria","tag":"hy-out","settings":{"version":2,"address":"hy.example.com","port":443},
  66. "streamSettings":{"network":"hysteria","security":"tls","hysteriaSettings":{"version":2,"auth":"a"},
  67. "finalmask":{"udp":[{"type":"salamander","settings":{"password":"abc"}}]}}}]}`)
  68. }},
  69. }
  70. for _, tc := range tests {
  71. t.Run(tc.name, func(t *testing.T) {
  72. setupBulkDB(t)
  73. if err := tc.save(t); err == nil || !strings.Contains(err.Error(), want) {
  74. t.Fatalf("save err = %v, want one containing %q", err, want)
  75. }
  76. })
  77. }
  78. }