I want to create a solidity function that will be external/public will be callable only through dapp and not from etherscan.io. Is there any way, like modifier or third-party?
The idea behind the blockchain is that it's permissionless and transparent. Anyone can verify the blockchain state at any point. Etherscan is just one such UI and anyone can create a front-end to read the state (calling view functions).
Regarding writing to the blockchain, anyone with a valid signature can call the external/public functions. So whatever you can do via your dapp, can be done by any other method, as in the end, dapps are just pieces of code that interact with the blockchain via PRC providers.
However, if you really want to control access, what you can do is to make the contracts require multi-sig. Let's say you have a function that can be called by users to change the state. You can modify it to require valid signatures from another approver address that you control, also as part of the function call. Then you can configure your dapp to provide the required signature from your backend, whenever your users want to interact with the contracts. This way, even though the functions can be called by anyone (like on etherscan), only those called from your dapp will trigger that approver address signature.
This is just a theoretical idea of how it could be implemented. But practically you should avoid using this pattern as it makes the whole smart contract interaction centralised, thus defeating a part of the blockchain's ideology.
There is a modifier onlyOwner/OnlybyOwner that allows only for the ones who deployed the contract to call the function. Additional owners can be added by the original Owner. ( Look at OpenZeppelin here)
But you can create a custom one too, to better suit your requirements.
ShortAnswer: You can create a modifier that will limit as to who can call a function. You can even hardcode addressess that will be the only ones allowed to call the said function.
I do not believe this is possible. If someone can find your contract address they can call it. You can still store data off chain, though that data would no longer be immutable. If this isn't a problem for your use case, then you can always provide the off chain data to the contract function at a later time.