mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-01-03 16:13:30 +08:00
chore: new rule
This commit is contained in:
parent
3fd954d185
commit
1f7a883bfc
@ -263,8 +263,8 @@ type RawTuicServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawMitm struct {
|
type RawMitm struct {
|
||||||
Port int `yaml:"port" json:"port"`
|
Port int `yaml:"port" json:"port"`
|
||||||
Rules []string `yaml:"rules" json:"rules"`
|
Rules []rewrites.RawMitmRule `yaml:"rules" json:"rules"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawConfig struct {
|
type RawConfig struct {
|
||||||
@ -456,7 +456,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
|||||||
},
|
},
|
||||||
MITM: RawMitm{
|
MITM: RawMitm{
|
||||||
Port: 0,
|
Port: 0,
|
||||||
Rules: []string{},
|
Rules: []rewrites.RawMitmRule{},
|
||||||
},
|
},
|
||||||
Profile: Profile{
|
Profile: Profile{
|
||||||
StoreSelected: true,
|
StoreSelected: true,
|
||||||
|
@ -162,6 +162,8 @@ func (m *Metadata) SourceAddress() string {
|
|||||||
func (m *Metadata) SourceDetail() string {
|
func (m *Metadata) SourceDetail() string {
|
||||||
if m.Type == INNER {
|
if m.Type == INNER {
|
||||||
return fmt.Sprintf("%s", ClashName)
|
return fmt.Sprintf("%s", ClashName)
|
||||||
|
} else if m.Type == MITM {
|
||||||
|
return fmt.Sprintf("%s-MITM", ClashName)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package constant
|
package constant
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
regexp "github.com/dlclark/regexp2"
|
regexp "github.com/dlclark/regexp2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,6 +39,42 @@ const (
|
|||||||
|
|
||||||
type RewriteType int
|
type RewriteType int
|
||||||
|
|
||||||
|
// UnmarshalYAML unserialize RewriteType with yaml
|
||||||
|
func (e *RewriteType) UnmarshalYAML(unmarshal func(any) error) error {
|
||||||
|
var tp string
|
||||||
|
if err := unmarshal(&tp); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mode, exist := RewriteTypeMapping[tp]
|
||||||
|
if !exist {
|
||||||
|
return errors.New("invalid MITM Action")
|
||||||
|
}
|
||||||
|
*e = mode
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalYAML serialize RewriteType with yaml
|
||||||
|
func (e RewriteType) MarshalYAML() (any, error) {
|
||||||
|
return e.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unserialize RewriteType with json
|
||||||
|
func (e *RewriteType) UnmarshalJSON(data []byte) error {
|
||||||
|
var tp string
|
||||||
|
json.Unmarshal(data, &tp)
|
||||||
|
mode, exist := RewriteTypeMapping[tp]
|
||||||
|
if !exist {
|
||||||
|
return errors.New("invalid MITM Action")
|
||||||
|
}
|
||||||
|
*e = mode
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON serialize RewriteType with json
|
||||||
|
func (e RewriteType) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(e.String())
|
||||||
|
}
|
||||||
|
|
||||||
func (rt RewriteType) String() string {
|
func (rt RewriteType) String() string {
|
||||||
switch rt {
|
switch rt {
|
||||||
case MitmReject:
|
case MitmReject:
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -31,6 +32,8 @@ func (*RewriteHandler) HandleRequest(session *mitm.Session) (*http.Request, *htt
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("[MITM] %s <- request %s", rule.RuleType().String(), request.URL.String())
|
||||||
|
|
||||||
switch rule.RuleType() {
|
switch rule.RuleType() {
|
||||||
case C.MitmReject:
|
case C.MitmReject:
|
||||||
response = session.NewResponse(http.StatusNotFound, nil)
|
response = session.NewResponse(http.StatusNotFound, nil)
|
||||||
@ -113,6 +116,8 @@ func (*RewriteHandler) HandleResponse(session *mitm.Session) *http.Response {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("[MITM] %s <- response %s", rule.RuleType().String(), request.URL.String())
|
||||||
|
|
||||||
switch rule.RuleType() {
|
switch rule.RuleType() {
|
||||||
case C.MitmResponseHeader:
|
case C.MitmResponseHeader:
|
||||||
if len(response.Header) == 0 {
|
if len(response.Header) == 0 {
|
||||||
@ -182,7 +187,7 @@ func matchRewriteRule(url string, isRequest bool) (rr C.Rewrite, sub []string, f
|
|||||||
if isRequest {
|
if isRequest {
|
||||||
found = rewrites.SearchInRequest(func(r C.Rewrite) bool {
|
found = rewrites.SearchInRequest(func(r C.Rewrite) bool {
|
||||||
sub, err := r.URLRegx().FindStringMatch(url)
|
sub, err := r.URLRegx().FindStringMatch(url)
|
||||||
if err != nil {
|
if err != nil || sub == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,12 +7,7 @@ import (
|
|||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseRewrite(line string) (C.Rewrite, error) {
|
func ParseRewrite(line RawMitmRule) (C.Rewrite, error) {
|
||||||
url, others, found := strings.Cut(strings.TrimSpace(line), "url")
|
|
||||||
if !found {
|
|
||||||
return nil, errInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
urlRegx *regexp.Regexp
|
urlRegx *regexp.Regexp
|
||||||
ruleType *C.RewriteType
|
ruleType *C.RewriteType
|
||||||
@ -22,57 +17,37 @@ func ParseRewrite(line string) (C.Rewrite, error) {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
url := line.Url
|
||||||
urlRegx, err = regexp.Compile(strings.Trim(url, " "), regexp.None)
|
urlRegx, err = regexp.Compile(strings.Trim(url, " "), regexp.None)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
others = strings.Trim(others, " ")
|
ruleType = &line.Action
|
||||||
first := strings.Split(others, " ")[0]
|
switch *ruleType {
|
||||||
for k, v := range C.RewriteTypeMapping {
|
case C.Mitm302, C.Mitm307:
|
||||||
if k == others {
|
{
|
||||||
ruleType = &v
|
rulePayload = line.New
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case C.MitmRequestHeader, C.MitmRequestBody, C.MitmResponseHeader, C.MitmResponseBody:
|
||||||
|
{
|
||||||
|
var old string
|
||||||
|
if line.Old == nil {
|
||||||
|
old = ".*"
|
||||||
|
} else {
|
||||||
|
old = *line.Old
|
||||||
|
}
|
||||||
|
|
||||||
if k != first {
|
re, err := regexp.Compile(old, regexp.Singleline)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
rs := trimArr(strings.Split(others, k))
|
|
||||||
l := len(rs)
|
|
||||||
if l > 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if l == 1 {
|
|
||||||
ruleType = &v
|
|
||||||
rulePayload = rs[0]
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
ruleRegx, err = regexp.Compile(rs[0], regexp.None)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
ruleRegx = re
|
||||||
|
|
||||||
ruleType = &v
|
rulePayload = line.New
|
||||||
rulePayload = rs[1]
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ruleType == nil {
|
|
||||||
return nil, errInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
return NewRewriteRule(urlRegx, *ruleType, ruleRegx, rulePayload), nil
|
return NewRewriteRule(urlRegx, *ruleType, ruleRegx, rulePayload), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimArr(arr []string) (r []string) {
|
|
||||||
for _, e := range arr {
|
|
||||||
if s := strings.Trim(e, " "); s != "" {
|
|
||||||
r = append(r, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package rewrites
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/draw"
|
|
||||||
"image/png"
|
|
||||||
"regexp"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/constant"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseRewrite(t *testing.T) {
|
|
||||||
line0 := `^https?://example\.com/resource1/3/ url reject-dict`
|
|
||||||
line1 := `^https?://example\.com/(resource2)/ url 307 https://example.com/new-$1`
|
|
||||||
line2 := `^https?://example\.com/resource4/ url request-header (\r\n)User-Agent:.+(\r\n) request-header $1User-Agent: Fuck-Who$2`
|
|
||||||
line3 := `should be error`
|
|
||||||
|
|
||||||
c0, err0 := ParseRewrite(line0)
|
|
||||||
c1, err1 := ParseRewrite(line1)
|
|
||||||
c2, err2 := ParseRewrite(line2)
|
|
||||||
_, err3 := ParseRewrite(line3)
|
|
||||||
|
|
||||||
assert.NotNil(t, err3)
|
|
||||||
|
|
||||||
assert.Nil(t, err0)
|
|
||||||
assert.Equal(t, c0.RuleType(), constant.MitmRejectDict)
|
|
||||||
|
|
||||||
assert.Nil(t, err1)
|
|
||||||
assert.Equal(t, c1.RuleType(), constant.Mitm307)
|
|
||||||
assert.Equal(t, c1.URLRegx(), regexp.MustCompile(`^https?://example\.com/(resource2)/`))
|
|
||||||
assert.Equal(t, c1.RulePayload(), "https://example.com/new-$1")
|
|
||||||
|
|
||||||
assert.Nil(t, err2)
|
|
||||||
assert.Equal(t, c2.RuleType(), constant.MitmRequestHeader)
|
|
||||||
assert.Equal(t, c2.RuleRegx(), regexp.MustCompile(`(\r\n)User-Agent:.+(\r\n)`))
|
|
||||||
assert.Equal(t, c2.RulePayload(), "$1User-Agent: Fuck-Who$2")
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test1PxPNG(t *testing.T) {
|
|
||||||
m := image.NewRGBA(image.Rect(0, 0, 1, 1))
|
|
||||||
|
|
||||||
draw.Draw(m, m.Bounds(), &image.Uniform{C: color.Transparent}, image.Point{}, draw.Src)
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
|
|
||||||
assert.Nil(t, png.Encode(buf, m))
|
|
||||||
|
|
||||||
fmt.Printf("len: %d\n", buf.Len())
|
|
||||||
fmt.Printf("% #x\n", buf.Bytes())
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
package rewrites
|
package rewrites
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
regexp "github.com/dlclark/regexp2"
|
regexp "github.com/dlclark/regexp2"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -11,7 +10,12 @@ import (
|
|||||||
"github.com/gofrs/uuid"
|
"github.com/gofrs/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errInvalid = errors.New("invalid rewrite rule")
|
type RawMitmRule struct {
|
||||||
|
Url string `yaml:"url" json:"url"`
|
||||||
|
Action C.RewriteType `yaml:"action" json:"action"`
|
||||||
|
Old *string `yaml:"old" json:"old"`
|
||||||
|
New string `yaml:"new" json:"new"`
|
||||||
|
}
|
||||||
|
|
||||||
type RewriteRule struct {
|
type RewriteRule struct {
|
||||||
id string
|
id string
|
||||||
|
@ -561,6 +561,10 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, rule := range getRules(metadata) {
|
for _, rule := range getRules(metadata) {
|
||||||
|
if metadata.Type == C.MITM && rule.Adapter() == "MITM" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if !resolved && shouldResolveIP(rule, metadata) {
|
if !resolved && shouldResolveIP(rule, metadata) {
|
||||||
func() {
|
func() {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user