### Description

It is impossible to create a follower index with a `$` character in its name (please note, it is possible to create a regular index with `$` in its name).

This could be reproduced by rest request:
```
PUT /my-index/_ccr/follow
{
    "remote_cluster": "my-remote-cluster",
    "leader_index": "my-index$follower"
}
```

or `CcrIntegTestCase`:

```
    public void testFollowIndex() throws Exception {
        assertAcked(leaderClient().admin().indices().prepareCreate("my$index"));
        setupRemoteCluster();
        final PutFollowAction.Request followRequest = putFollow("my$index", "my$index");
        followerClient().execute(PutFollowAction.INSTANCE, followRequest).get();
    }
```

This is happening as during initial follow phase we restore the leader cluster from the remote using a snapshot restore.
Corresponding request is created with index name added to `RestoreSnapshotRequest#renamePattern` (regexp) without escaping `$`.

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportPutFollowAction.java
}
    }
    private void afterRestoreStarted(
        Client clientWithHeaders,
        PutFollowAction.Request request,
        ActionListener<PutFollowAction.Response> originalListener,
        RestoreService.RestoreCompletionResponse response
    ) {
        final ActionListener<PutFollowAction.Response> listener;
        if (ActiveShardCount.NONE.equals(request.waitForActiveShards())) {
            originalListener.onResponse(new PutFollowAction.Response(true, false, false));
            listener = new ActionListener<>() {
                @Override
                public void onResponse(PutFollowAction.Response response) {
                    logger.debug("put follow {} completed with {}", request, response);
                }
                @Override
                public void onFailure(Exception e) {
                    logger.debug(() -> "put follow " + request + " failed during the restore process", e);
                }
            };
        } else {
            listener = originalListener;
        }
        RestoreClusterStateListener.createAndRegisterListener(
            clusterService,
            response,
            listener.delegateFailure((delegatedListener, restoreSnapshotResponse) -> {
                RestoreInfo restoreInfo = restoreSnapshotResponse.getRestoreInfo();
                if (restoreInfo == null) {