Proxy Chain
Clash Nyanpasu inherits the proxy chain feature from Clash Verge and can implement a proxy chain through two types of chains: Script or Merge. The content of this section is adapted from Clash Verge documentation[1].
What is a Proxy Chain?
A proxy chain refers to the post-processing chain of a Profile. A profile can go through nodes such as A, B, C, or even more chain processing nodes, where the configuration is modified using scripts or expressions to generate a final proxy configuration. Multiple nodes are processed sequentially, forming a chain structure. You can customize the chain to enable certain nodes for different profiles or globally, thereby creating your own proxy chain.
The following diagram shows the current chain processing structure.
Merge Processing
Note
Starting from version 1.6.0, we have enabled custom keywords to support the . object access operator and perform recursive merging by default, avoiding direct overwriting of existing configurations. If you need to override, use override__x.y.z to apply the old behavior. Additionally, we plan to introduce a new pipeline node for pipeline expression operations, simplifying GUI-based configuration.
This processing node provides configuration merging functionality similar to OpenClash. It achieves this by defining the following rules for overwriting configurations.
Note
When using other fields like dns, tun, etc., you need to select the corresponding fields in the Clash Fields section on the settings page. Fields that are not selected will be ignored. Moreover, Merge rules are executed in top-down order.
Merge Rules
append__x.y.z- Appends the content of thex.y.zfield to the end of the originalx.y.zlist. Ifx.y.zdoes not exist or is not an array, it will be ignored, and a log warning will be triggered.prepend__x.y.z- Adds the content of thex.y.zfield to the beginning of the originalx.y.zlist. Ifx.y.zdoes not exist or is not an array, it will be ignored, and a log warning will be triggered.override__x.y.z- Directly overrides the content of thex.y.zfield. Ifx.y.zdoes not exist, it will be ignored, and a log warning will be triggered.filter__x.y.z- Filters or modifies the content of thex.y.zfield. For supported types, refer tofilterSupported Operations.- Other fields - Fields are recursively merged and will not directly overwrite the original configuration.
More examples can be found in the Merge Unit Test Cases.
filter Supported Operations
Filtering Lists
The filter__x.y.z: string operation filters a list using a Lua expression where item represents the current element. The expression must return a bool. If the expression encounters an error, a log warning will be triggered.
Here is an example of removing trojan proxies:
filter__proxies: |
item.type ~= 'trojan'Modifying Lists Using Expressions
This operation is similar to the map operation in other languages. It modifies matched items using the expr expression. The syntax is as follows:
filter__x.y.z:
when: string # Lua expression, where item is the current element, returns a boolean value
expr: string # Lua expression, where item is the current element, returns the modified itemHere’s an example of modifying the port of trojan proxies to 443:
filter__proxies:
when: |
item.type == 'trojan'
expr: |
item.port = 443
return itemMerging Fields
This operation is similar to the map operation in other languages, merging matched items using the merge table. The syntax is as follows:
filter__x.y.z:
when: string # Lua expression, where item is the current element, returns a boolean value
merge: object # Object to be merged recursively, future support for arrays might be consideredHere is an example of adding the icon field to the Spotify proxy group:
filter__proxy-groups:
when: |
item.name == 'Spotify'
merge:
icon: 'https://example.com/spotify.png'Directly Overwriting Fields
This operation is similar to the map operation in other languages but directly overwrites the matched item. The syntax is as follows:
filter__x.y.z:
when: string # Lua expression, where item is the current element, returns a boolean value
override: any # Value to overrideHere is an example of forcibly overriding the Spotify proxy group:
filter__proxy-groups:
when: |
item.name == 'Spotify'
override:
name: 'Spotify'
type: select
proxies:
- Proxies
- DIRECT
- HK
- JP
- SG
- TW
- USRemoving Fields
This operation is similar to the map operation in other languages but removes keys from the matched item using the remove field. The syntax is as follows:
filter__x.y.z:
when: string # Lua expression, where item is the current element, returns a boolean value
remove: Array<string | int> # List of keys to remove. Keys are strings for objects and numbers for arrays.Here’s an example of removing the first proxy from the proxies field of the Spotify proxy group:
filter__proxy-groups:
when: |
item.name == 'Spotify'
remove:
- proxies.0Chained Operations
The filter operation supports list types, where each element is a filter operation. This allows for chained processing of multiple operations.
Here’s an example that adds the icon field to both the Spotify and Netflix proxy groups:
filter__proxy-groups:
- when: |
item.name == 'Spotify'
merge:
icon: 'https://example.com/spotify.png'
- when: |
item.name == 'Netflix'
merge:
icon: 'https://example.com/netflix.png'Script Processing
Note
We plan to introduce the unstable_get method in version 1.6.2, allowing HTTP GET requests to fetch remote content for processing.
For more examples, please refer to the next section.
JavaScript Node
This processing node currently provides JavaScript processing based on BoaJS, similar to the Mixins or preprocessing feature in CFW.
The script accepts a function with the signature export default function main(config: ClashConfig): ClashConfig, where ClashConfig is the Clash configuration type. The return value of the script will be used as the final configuration.
Here’s an example of adding rules through a script:
export default function main(config) {
const rules = ['DOMAIN-SUFFIX,google.com,PROXY', 'DOMAIN,example.org,PROXY']
config.rules = [...config.rules, ...rules]
return config
}Lua Processing Node
This processing node provides Lua scripting functionality based on mlua, compatible with Lua 5.4 syntax, and includes a secure standard library preset.
The processing module exposes a config variable that contains the current Clash configuration. Users can modify the config variable, and the result will be used as the final configuration.
Here’s an example of adding rules through a Lua script:
local rules = {
'DOMAIN-SUFFIX,google.com,PROXY',
'DOMAIN,example.org,PROXY',
}
for _, rule in ipairs(rules) do
table.insert(config.rules, rule)
end
return config